Skip to content

Commit d74b13c

Browse files
author
Jean Baptiste Favre
committed
Update ssl_certificates_check plugin for SampleProbe
1 parent 29b2c31 commit d74b13c

File tree

1 file changed

+34
-119
lines changed

1 file changed

+34
-119
lines changed

scripts/ssl_certificates_check.py

Lines changed: 34 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
3-
''' Copyright (c) 2013 Jean Baptiste Favre.
4-
Sample script for Zabbix integration SSL endpoints.
5-
'''
3+
64
import optparse
75
import yaml
86
import protobix
@@ -13,12 +11,11 @@
1311
import sys
1412
from datetime import datetime
1513

16-
class SSLEndpointCheck(object):
14+
CA_CERTS = "/etc/ssl/certs/ca-certificates.crt"
1715

18-
__version__ = '0.0.8'
19-
ZBX_CONN_ERR = 'ERR - unable to send data to Zabbix [%s]'
16+
class SSLEndpointCheck(protobix.SampleProbe):
2017

21-
CA_CERTS = "/etc/ssl/certs/ca-certificates.crt"
18+
__version__ = '0.0.9'
2219

2320
def _check_expiration(self, cert):
2421
''' Return the numbers of day before expiration. False if expired. '''
@@ -27,49 +24,65 @@ def _check_expiration(self, cert):
2724
expire_date = datetime.strptime(cert['notAfter'],
2825
"%b %d %H:%M:%S %Y %Z")
2926
except:
30-
raise Exception('Certificate date format unknow.')
27+
exit_error(1, 'Certificate date format unknow.')
3128
expire_in = expire_date - datetime.now()
3229
if expire_in.days > 0:
3330
return expire_in.days
3431
else:
3532
return False
3633

37-
def _get_certificate(self, HOST, PORT=443):
34+
def _get_certificate(self, host, port=443):
3835
# Connect to the host and get the certificate
3936
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
40-
sock.connect((HOST, PORT))
37+
sock.connect((host, port))
4138
ssl_sock = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_REQUIRED,
4239
ca_certs=CA_CERTS)
4340
cert = ssl_sock.getpeercert()
4441
sock.shutdown(socket.SHUT_RDWR)
4542
sock.close()
4643
return cert
4744

48-
def _get_discovery(self):
49-
discovery_data = { 'ssl.certificate.discovery': []}
45+
def _parse_args(self):
46+
# Parse the script arguments
47+
# Common part
48+
parser = super( SSLEndpointCheck, self)._parse_args()
49+
50+
(options, args) = parser.parse_args()
51+
return (options, args)
52+
53+
def _init_probe(self):
54+
self.hostname = socket.getfqdn()
55+
56+
''' Load config file '''
57+
with open(self.options.config, 'r') as f:
58+
config = yaml.load(f)
59+
self.endpoints = config['endpoints']
5060

61+
def _get_discovery(self, hostname):
62+
data = { 'ssl.certificate.discovery': [] }
5163
for endpoint in self.endpoints:
5264
try:
53-
cert = self._get_certificate(endpoint, 443)
65+
cert = self._get_certificate( host = endpoint,
66+
port = 443 )
5467
common_name = cert['subjectAltName'][0][1]
5568
element = { '{#SSLCERTSERIAL}': common_name + endpoint,
5669
'{#SSLCERTNAME}': common_name,
5770
'{#SSLCERTENDPOINT}': endpoint }
58-
discovery_data['ssl.certificate.discovery'].append(element)
71+
data['ssl.certificate.discovery'].append(element)
5972
except:
6073
pass
74+
return { hostname: data }
6175

62-
return discovery_data
63-
64-
def _get_metrics(self):
76+
def _get_metrics(self, hostname):
6577
data = {}
6678
for endpoint in self.endpoints:
6779
try:
68-
cert = self.get_certificate(endpoint, 443)
80+
cert = self._get_certificate( host = endpoint,
81+
port = 443 )
6982
common_name = cert['subjectAltName'][0][1]
7083
zbx_key = "ssl.certificate.expires_in_days[{0},{1}]"
7184
zbx_key = zbx_key.format(common_name, endpoint)
72-
data[zbx_key] = self.check_expiration(cert)
85+
data[zbx_key] = self._check_expiration(cert)
7386

7487
zbx_key = "ssl.certificate.check_status[{0}]"
7588
zbx_key = zbx_key.format(endpoint)
@@ -80,107 +93,9 @@ def _get_metrics(self):
8093
data[zbx_key] = 0
8194
pass
8295
data['ssl.certificate.zbx_version'] = self.__version__
83-
84-
return data
85-
86-
def _parse_args(self):
87-
''' Parse the script arguments'''
88-
parser = optparse.OptionParser()
89-
90-
parser.add_option("-d", "--dry", action="store_true",
91-
help="Performs SSL certificates checks but do not send "
92-
"anything to the Zabbix server. Can be used "
93-
"for both Update & Discovery mode")
94-
parser.add_option("-D", "--debug", action="store_true",
95-
help="Enable debug mode. This will prevent bulk send "
96-
"operations and force sending items one after the "
97-
"other, displaying result for each one")
98-
parser.add_option("-v", "--verbose", action="store_true",
99-
help="When used with debug option, will force value "
100-
"display for each items managed. Beware that it "
101-
"can be pretty too much verbose, specialy for LLD")
102-
103-
mode_group = optparse.OptionGroup(parser, "Program Mode")
104-
mode_group.add_option("--update-items", action="store_const",
105-
dest="mode", const="update_items",
106-
help="Get & send items to Zabbix. This is the default "
107-
"behaviour even if option is not specified")
108-
mode_group.add_option("--discovery", action="store_const",
109-
dest="mode", const="discovery",
110-
help="If specified, will perform Zabbix Low Level "
111-
"Discovery against domain names to check. "
112-
"Default is to get & send items")
113-
parser.add_option_group(mode_group)
114-
parser.set_defaults(mode="update_items")
115-
116-
polling_options = optparse.OptionGroup(parser, "Zabbix configuration")
117-
polling_options.add_option("--zabbix-server", metavar="HOST",
118-
default="localhost",
119-
help="The hostname of Zabbix server or "
120-
"proxy, default is localhost.")
121-
polling_options.add_option("--zabbix-port", metavar="PORT", default=10051,
122-
help="The port on which the Zabbix server or "
123-
"proxy is running, default is 10051.")
124-
parser.add_option_group(polling_options)
125-
126-
(options, args) = parser.parse_args()
127-
128-
return (options, args)
129-
130-
def _init_container(self):
131-
zbx_container = protobix.DataContainer(
132-
data_type = 'items',
133-
zbx_host = self.options.zabbix_server,
134-
zbx_port = int(self.options.zabbix_port),
135-
debug = self.options.debug,
136-
dryrun = self.options.dry
137-
)
138-
return zbx_container
139-
140-
def run(self, conf_file='/etc/zabbix/ssl_certificates_check.yaml'):
141-
(self.options, args) = self._parse_args()
142-
hostname = socket.getfqdn()
143-
144-
# Step 1: init container
145-
try:
146-
zbx_container = self._init_container()
147-
except:
148-
return 1
149-
150-
# Step 2: get data
151-
try:
152-
''' Load config file '''
153-
with open(conf_file, 'r') as f:
154-
config = yaml.load(f)
155-
self.endpoints = config['endpoints']
156-
157-
data = {}
158-
if self.options.mode == "update_items":
159-
zbx_container.set_type("items")
160-
data[hostname] = self._get_metrics()
161-
elif self.options.mode == "discovery":
162-
zbx_container.set_type("lld")
163-
data[hostname] = self._get_discovery()
164-
except:
165-
return 2
166-
167-
# Step 3: format & load data into container
168-
try:
169-
zbx_container.add(data)
170-
except:
171-
return 3
172-
173-
# Step 4: send container data to Zabbix server
174-
try:
175-
zbx_container.send(zbx_container)
176-
except protobix.SenderException as zbx_e:
177-
if self.options.debug:
178-
print self.ZBX_CONN_ERR % zbx_e.err_text
179-
return 4
180-
# Everything went fine. Let's return 0 and exit
181-
return 0
96+
return { hostname: data }
18297

18398
if __name__ == '__main__':
18499
ret = SSLEndpointCheck().run()
185100
print ret
186-
sys.exit(ret)
101+
sys.exit(ret)

0 commit comments

Comments
 (0)