├── conf ├── zabbix_letsencrypt └── letsencrypt.conf ├── scripts └── letsencrypt │ ├── cert_discovery.py │ └── cert_check.py ├── README.md └── zbx_letsencrypt_templates.xml /conf/zabbix_letsencrypt: -------------------------------------------------------------------------------- 1 | Cmnd_Alias ZABB = /etc/zabbix/scripts/letsencrypt/cert_discovery.py, /etc/zabbix/scripts/letsencrypt/cert_check.py 2 | Defaults:zabbix !requiretty 3 | zabbix ALL=NOPASSWD: ZABB 4 | -------------------------------------------------------------------------------- /conf/letsencrypt.conf: -------------------------------------------------------------------------------- 1 | UserParameter=letsencrypt_cert_discovery,sudo /etc/zabbix/scripts/letsencrypt/cert_discovery.py 2 | UserParameter=letsencrypt_cert_check[*],sudo /etc/zabbix/scripts/letsencrypt/cert_check.py $1 3 | UserParameter=certbot.version,/usr/bin/certbot --version 4 | UserParameter=letsencrypt_cert_version[*],grep "version =" < /etc/letsencrypt/renewal/$1.conf 5 | UserParameter=letsencrypt_cert_account[*],grep "account =" < /etc/letsencrypt/renewal/$1.conf 6 | -------------------------------------------------------------------------------- /scripts/letsencrypt/cert_discovery.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | 5 | 6 | def main(): 7 | cert_path = '/etc/letsencrypt/live/' 8 | domains_list = list(filter(lambda x: os.path.isdir(os.path.join(cert_path, x)), os.listdir(cert_path))) 9 | data = '' 10 | count = 1 11 | for domain in domains_list: 12 | cert = cert_path + domain + '/cert.pem' 13 | if os.path.isfile(cert): 14 | if count == 1: 15 | data += '{"data": [' 16 | if not count == len(domains_list): 17 | data += '{"{#DOMAIN}": "' + domain + '"}, ' 18 | else: 19 | data += '{"{#DOMAIN}": "' + domain + '"}]}' 20 | count += 1 21 | print(data) 22 | 23 | 24 | if __name__ == '__main__': 25 | main() 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zabbix_letsencrypt 2 | 3 | Zabbix template for letsencrypt certificates monitoring. 4 | 5 | 6 | ## Version 2023-01-23 7 | - Convert scripts to python3 - tested with zabbix 6.0.6 8 | 9 | 10 | ## Version 2019-04-30 11 | - Ignore files in cert folder (0.32 certbot puts a readme file in that folder) 12 | 13 | 14 | ## Version 2019-01-22 15 | - Added support to detect certbot version 16 | - Trigger when certbot version below 0.28 17 | 18 | ## System requirements 19 | 20 | - python 21 | 22 | ## Install 23 | 24 | Don't forget change paths: 25 | 26 | 1. Copy sudo permissions ```cp -r ./zabbix_letsencrypt/conf/zabbix_letsencrypt /etc/sudoers.d/``` 27 | 28 | 2. Copy scripts: ```cp -r ./zabbix_letsencrypt/scripts/letsencrypt /etc/zabbix/scripts/``` 29 | 30 | 3. Copy zabbix conf: ```cp -r ./zabbix_letsencrypt/conf/letsencrypt.conf /etc/zabbix/zabbix_agent.d/``` 31 | 32 | 4. Restart zabbix agent: ```/etc/init.d/zabbix_agent restart``` 33 | 34 | 5. Import template to Zabbix web. 35 | -------------------------------------------------------------------------------- /scripts/letsencrypt/cert_check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import subprocess 5 | import time 6 | import sys 7 | 8 | 9 | def days_left(cert): 10 | if os.path.isfile(cert): 11 | try: 12 | end_date = subprocess.check_output( 13 | 'openssl x509 -enddate -noout -in ' + cert, shell=True).decode('utf-8').replace('\n', '').split('=')[1] 14 | end_date_unix_time = subprocess.check_output( 15 | 'date -d "' + end_date + '" +%s', shell=True).decode('utf-8').replace('\n', '') 16 | except subprocess.CalledProcessError: 17 | print('ZBX_NOTSUPPORTED') 18 | days_left = (int(end_date_unix_time) - int(time.time())) / 86400 19 | if days_left < 0: 20 | print(0) 21 | else: 22 | print(int(round(days_left,0))) 23 | else: 24 | print('ZBX_NOTSUPPORTED') 25 | 26 | 27 | def main(): 28 | cert_path = '/etc/letsencrypt/live/' 29 | cert = cert_path + sys.argv[-1:][0]+ '/cert.pem' 30 | days_left(cert) 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /zbx_letsencrypt_templates.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0 4 | 2019-01-22T07:39:01Z 5 | 6 | 7 | Templates 8 | 9 | 10 | 11 | 537 | 538 | 539 | 540 | {Template App Letsencrypt:certbot.version.last()}<0.28 541 | 0 542 | 543 | Certbot older than version 0.28 ({ITEM.VALUE}) 544 | 0 545 | 546 | 547 | 0 548 | 3 549 | 550 | 0 551 | 0 552 | 553 | 554 | 555 | 556 | 557 | --------------------------------------------------------------------------------