├── .gitignore ├── externalscripts ├── list.sh ├── ssl_check.json ├── zext_ssl_cert.sh └── whois_expire.sh ├── Template Domain check via url.yaml ├── Template Domain check via file.yaml ├── README.md ├── Template SSL check via file.yaml └── Template SSL check via url.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /externalscripts/list.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /usr/lib/zabbix/externalscripts/ 4 | cat $1 5 | -------------------------------------------------------------------------------- /externalscripts/ssl_check.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"url": "mail.ru","port": "443"}, 3 | {"url": "yandex.ru","port": "443"} 4 | ] -------------------------------------------------------------------------------- /externalscripts/zext_ssl_cert.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | #------------------------------------------------------------ 3 | # zext_ssl_cert.sh 4 | # Script checks for number of days until certificate expires or the issuing authority 5 | # depending on switch passed on command line. 6 | # 7 | #Based on script from aperto.fr (http://aperto.fr/cms/en/blog/15-blog-en/15-ssl-certificate-expiration-monitoring-with-zabbix.html) 8 | #with additions by racooper@tamu.edu 9 | #------------------------------------------------------------ 10 | 11 | DEBUG=0 12 | if [ $DEBUG -gt 0 ] 13 | then 14 | exec 2>>/tmp/my.log 15 | set -x 16 | fi 17 | 18 | f=$1 19 | host=$2 20 | port=$3 21 | sni=$4 22 | proto=$5 23 | 24 | if [ -z "$sni" ] 25 | then 26 | servername=$host 27 | else 28 | servername=$sni 29 | fi 30 | 31 | if [ -n "$proto" ] 32 | then 33 | starttls="-starttls $proto" 34 | fi 35 | 36 | case $f in 37 | -d) 38 | fix_broken_pipe=`openssl s_client -servername $servername -connect $host:$port -showcerts $starttls /dev/null | 39 | sed -n '/BEGIN CERTIFICATE/,/END CERT/p'` 40 | 41 | end_date=`echo "$fix_broken_pipe" | openssl x509 -enddate -noout 2>/dev/null | 42 | sed -n 's/notAfter=//p' | 43 | sed 's/ GMT//g'` 44 | #end_date=`openssl s_client -servername $servername -host $host -port $port -showcerts $starttls -prexit /dev/null | 45 | # sed -n '/BEGIN CERTIFICATE/,/END CERT/p' | 46 | # openssl x509 -text 2>/dev/null | 47 | # sed -n 's/ *Not After : *//p'` 48 | 49 | if [ -n "$end_date" ] 50 | then 51 | end_date_seconds=`date '+%s' --date "$end_date"` 52 | now_seconds=`date '+%s'` 53 | echo "($end_date_seconds-$now_seconds)/24/3600" | bc 54 | fi 55 | ;; 56 | 57 | -i) 58 | fix_broken_pipe=`openssl s_client -servername $servername -connect $host:$port -showcerts $starttls /dev/null | 59 | sed -n '/BEGIN CERTIFICATE/,/END CERT/p'` 60 | 61 | issue_dn=`echo "$fix_broken_pipe" | openssl x509 -issuer -noout 2>/dev/null | 62 | sed -n 's/issuer=//p'` 63 | #issue_dn=`openssl s_client -servername $servername -host $host -port $port -showcerts $starttls -prexit /dev/null | 64 | # sed -n '/BEGIN CERTIFICATE/,/END CERT/p' | 65 | # openssl x509 -text 2>/dev/null | 66 | # sed -n 's/ *Issuer: *//p'` 67 | 68 | if [ -n "$issue_dn" ] 69 | then 70 | issuer=`echo $issue_dn | sed -n 's/.*CN=*//p'` 71 | echo $issuer 72 | fi 73 | ;; 74 | *) 75 | echo "usage: $0 [-i|-d] hostname port sni" 76 | echo " -i Show Issuer" 77 | echo " -d Show valid days remaining" 78 | ;; 79 | esac 80 | -------------------------------------------------------------------------------- /Template Domain check via url.yaml: -------------------------------------------------------------------------------- 1 | zabbix_export: 2 | version: '6.2' 3 | date: '2023-03-26T10:25:27Z' 4 | template_groups: 5 | - 6 | uuid: 7df96b18c230490a9a0a9e2307226338 7 | name: Templates 8 | templates: 9 | - 10 | uuid: 5e1c006f4b67440590f8f2191f204228 11 | template: 'Template Domain check via url' 12 | name: 'Template Domain check via url' 13 | groups: 14 | - 15 | name: Templates 16 | discovery_rules: 17 | - 18 | uuid: 27d1c7fa874647dc850c2f2ccb4157f5 19 | name: 'Domains discovery via URL' 20 | type: HTTP_AGENT 21 | key: domain_names_discovery 22 | delay: 1h 23 | lifetime: 60d 24 | item_prototypes: 25 | - uuid: 26507c9c412d413f9d7493a525a18f5d 26 | name: 'Domain {#DOMAIN_NAME} expire in' 27 | type: EXTERNAL 28 | key: 'whois_expire.sh[{#DOMAIN_NAME}]' 29 | delay: 1d 30 | trends: 730d 31 | units: day(s) 32 | tags: 33 | - tag: Application 34 | value: 'Domain checks' 35 | trigger_prototypes: 36 | - uuid: 8b556aeaf0684636a556045aae2d2dc8 37 | expression: 'last(/Template Domain check via url/whois_expire.sh[{#DOMAIN_NAME}])<=0' 38 | name: 'Domain {#DOMAIN_NAME} expired' 39 | priority: DISASTER 40 | - uuid: 27bd382372104e14a167834a74ef2af0 41 | expression: 'last(/Template Domain check via url/whois_expire.sh[{#DOMAIN_NAME}])<14' 42 | name: 'Domain {#DOMAIN_NAME} will expire in 14 days' 43 | priority: HIGH 44 | dependencies: 45 | - name: 'Domain {#DOMAIN_NAME} expired' 46 | expression: 'last(/Template Domain check via url/whois_expire.sh[{#DOMAIN_NAME}])<=0' 47 | - uuid: 077a856aa78f4bd4913c93b01d20e234 48 | expression: 'last(/Template Domain check via url/whois_expire.sh[{#DOMAIN_NAME}])<30' 49 | name: 'Domain {#DOMAIN_NAME} will expire in 30 days' 50 | priority: WARNING 51 | dependencies: 52 | - name: 'Domain {#DOMAIN_NAME} will expire in 14 days' 53 | expression: 'last(/Template Domain check via url/whois_expire.sh[{#DOMAIN_NAME}])<14' 54 | url: 'https://raw.githubusercontent.com/kulpin74/zabbix-ssl/master/externalscripts/ssl_check.json' 55 | lld_macro_paths: 56 | - 57 | lld_macro: '{#DOMAIN_NAME}' 58 | path: $.domain_name 59 | preprocessing: 60 | - 61 | type: JAVASCRIPT 62 | parameters: 63 | - | 64 | var urls = JSON.parse(value); 65 | var dom_names = []; 66 | for (var i = 0; i < urls.length; i++) { 67 | var j = urls[i].url.split('.'); 68 | var dn = j[j.length - 2] + '.' + j[j.length - 1]; 69 | if (dom_names.indexOf(dn) == -1) { 70 | dom_names.push(dn); 71 | } 72 | } 73 | var dnames = []; 74 | for (var i = 0; i < dom_names.length; i++) { 75 | dnames.push({'domain_name': dom_names[i]}); 76 | } 77 | return JSON.stringify(dnames); 78 | -------------------------------------------------------------------------------- /Template Domain check via file.yaml: -------------------------------------------------------------------------------- 1 | zabbix_export: 2 | version: '6.2' 3 | date: '2023-03-26T10:25:27Z' 4 | template_groups: 5 | - 6 | uuid: 7df96b18c230490a9a0a9e2307226338 7 | name: Templates 8 | templates: 9 | - 10 | uuid: b16bf4e6b1e645a49ff061a83647f2ad 11 | template: 'Template Domain check via file' 12 | name: 'Template Domain check via file' 13 | groups: 14 | - 15 | name: Templates 16 | discovery_rules: 17 | - 18 | uuid: f0f5caf81a9a4ba7aa16b5ccc4296e8c 19 | name: 'Domains discovery via file' 20 | type: EXTERNAL 21 | key: 'list.sh["ssl_check.json","1"]' 22 | delay: 1h 23 | lifetime: 60d 24 | item_prototypes: 25 | - 26 | uuid: 6df79ee6939244d5a1d854063dde8d8f 27 | name: 'Domain {#DOMAIN_NAME} expire in' 28 | type: EXTERNAL 29 | key: 'whois_expire.sh[{#DOMAIN_NAME}]' 30 | delay: 1d 31 | trends: 730d 32 | units: day(s) 33 | tags: 34 | - 35 | tag: Application 36 | value: 'Domain checks' 37 | trigger_prototypes: 38 | - 39 | uuid: 72ce8aaf74364d66893b7f2f9bcd4ac7 40 | expression: 'last(/Template Domain check via file/whois_expire.sh[{#DOMAIN_NAME}])<=0' 41 | name: 'Domain {#DOMAIN_NAME} expired' 42 | priority: DISASTER 43 | - 44 | uuid: 7803bdf2ade94f02ad74c140c0631148 45 | expression: 'last(/Template Domain check via file/whois_expire.sh[{#DOMAIN_NAME}])<14' 46 | name: 'Domain {#DOMAIN_NAME} will expire in 14 days' 47 | priority: HIGH 48 | dependencies: 49 | - 50 | name: 'Domain {#DOMAIN_NAME} expired' 51 | expression: 'last(/Template Domain check via file/whois_expire.sh[{#DOMAIN_NAME}])<=0' 52 | - 53 | uuid: dd7366cd97a4408196d48b74745cd4a6 54 | expression: 'last(/Template Domain check via file/whois_expire.sh[{#DOMAIN_NAME}])<30' 55 | name: 'Domain {#DOMAIN_NAME} will expire in 30 days' 56 | priority: WARNING 57 | dependencies: 58 | - 59 | name: 'Domain {#DOMAIN_NAME} will expire in 14 days' 60 | expression: 'last(/Template Domain check via file/whois_expire.sh[{#DOMAIN_NAME}])<14' 61 | lld_macro_paths: 62 | - 63 | lld_macro: '{#DOMAIN_NAME}' 64 | path: $.domain_name 65 | preprocessing: 66 | - 67 | type: JAVASCRIPT 68 | parameters: 69 | - | 70 | var urls = JSON.parse(value); 71 | var dom_names = []; 72 | for (var i = 0; i < urls.length; i++) { 73 | var j = urls[i].url.split('.'); 74 | var dn = j[j.length - 2] + '.' + j[j.length - 1]; 75 | if (dom_names.indexOf(dn) == -1) { 76 | dom_names.push(dn); 77 | } 78 | } 79 | var dnames = []; 80 | for (var i = 0; i < dom_names.length; i++) { 81 | dnames.push({'domain_name': dom_names[i]}); 82 | } 83 | return JSON.stringify(dnames); 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Checking domain name expiration date (with RDAP support) and SSL validity 2 | The standard approach assumes creating a host for each checked name, which is inconvenient and redundant, since several names can be bound to one ip address. 3 | The concept of collecting all monitored names into one node has been implemented. LLD is used for discovery. 4 | 5 | Now the general template has been divided into several, so you can only import the templates you need. 6 | 7 | ### Checking domain name expiration date 8 | 9 | For this task you can use one of two template: 10 | * `Template Domain check via file` - it used for getting domain names from file 11 | * `Template Domain check via url` - it used for getting domain names from url 12 | 13 | ### Checking SSL validity 14 | 15 | For this task you can use one of two template: 16 | * `Template SSL check via file` - it used for getting domain names from file 17 | * `Template SSL check via url` - it used for getting domain names from url 18 | 19 | 20 | Name's list are in json and it used to get domain names both the expiration check and SSL validity. 21 | Example of domain names list: 22 | ```json 23 | [ 24 | {"url": "mail.ru", "port": "443"}, 25 | {"url": "yandex.ru", "port": "443"} 26 | ] 27 | ``` 28 | 29 | If you use url for getting domain names you have to put the files `externalscripts/whois_expire.sh` and `externalscripts/zext_ssl_cert.sh` in the path for external Zabbix scripts and make its executable: `chmod +x zext_ssl_cert.sh whois_expire.sh`. 30 | 31 | If you want to use file to getting domain names you have to put all the files `externalscripts/*` in the path for external Zabbix scripts, make the *.sh files executable: `chmod +x zext_ssl_cert.sh list.sh whois_expire.sh`. 32 | In the file `ssl_check.json` enter data for monitoring. 33 | 34 | ## Проверка даты регистрации доменных имен (с поддержкой RDAP) и действительности SSL сертификатов 35 | Стандартный шаблон предполагает создание узла сети на каждое проверяемое имя, что неудобно и избыточно, так как несколько имен может быть привязано к одному ip адресу. 36 | Реализована концепция сбора всех наблюдаемых имен в один узел. Для обнаружения используется LLD. 37 | 38 | Шаблон был разделен на несколько отдельных, теперь вы можете импортировать только то что вам необходимо. 39 | 40 | ### Проверка даты регистрации доменных имен 41 | 42 | Для этой задачи используется один из двух шаблонов: 43 | * `Template Domain check via file` - для получения списка доменных имен из файла 44 | * `Template Domain check via url` - для получения списка доменных имен из url 45 | 46 | ### Проверка действительности SSL сертификатов 47 | 48 | Для этой задачи используется один из двух шаблонов: 49 | * `Template SSL check via file` - для получения списка доменных имен из файла 50 | * `Template SSL check via url` - для получения списка доменных имен из url 51 | 52 | 53 | Список имен сохраняется в json, и он используется для получения доменных имен и для проверки даты регистрации доменных имен и для проверки действительности SSL сертификатов. 54 | Example of domain names list: 55 | ```json 56 | [ 57 | {"url": "mail.ru", "port": "443"}, 58 | {"url": "yandex.ru", "port": "443"} 59 | ] 60 | ``` 61 | 62 | Если вы используете url для получения доенных имен необходимо положить файлы `externalscripts/whois_expire.sh` и `externalscripts/zext_ssl_cert.sh` в каталог внешних скриптов Zabbix исделать их исполняемыми: `chmod +x zext_ssl_cert.sh whois_expire.sh`. 63 | 64 | Если вы используете файл для получения доменных имен - необходимо положить положить все файлы `externalscripts/*` в каталог внешних скриптов Zabbix, файлы *.sh сделать исполняемыми: `chmod +x zext_ssl_cert.sh list.sh whois_expire.sh`. 65 | В файл `ssl_check.json` внести данные для мониторинга по аналогии с примером. 66 | -------------------------------------------------------------------------------- /externalscripts/whois_expire.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Prerequisite check 4 | check_dependencies() { 5 | local missing=0 6 | for cmd in curl jq date grep awk timeout whois; do 7 | if ! command -v "$cmd" >/dev/null 2>&1; then 8 | echo "Error: '$cmd' is not installed or not found in PATH." >&2 9 | missing=1 10 | fi 11 | done 12 | if [ "$missing" -ne 0 ]; then 13 | echo "Please install the missing prerequisites and try again." >&2 14 | exit 1 15 | fi 16 | } 17 | 18 | check_dependencies 19 | 20 | # Configuration - tuned for speed 21 | WHOIS_TIMEOUT=3 # seconds (reduced from 5) 22 | RDAP_TIMEOUT=1 # seconds (very aggressive) 23 | CACHE_FILE="/tmp/rdap_cache.$USER" 24 | 25 | # Pre-cached RDAP servers for instant lookups (updated) 26 | declare -A RDAP_SERVERS=( 27 | ["dev"]="https://pubapi.registry.google/rdap/domain/" 28 | ["app"]="https://pubapi.registry.google/rdap/domain/" 29 | ["page"]="https://pubapi.registry.google/rdap/domain/" 30 | ["com"]="https://rdap.verisign.com/com/v1/domain/" 31 | ["net"]="https://rdap.verisign.com/net/v1/domain/" 32 | ["org"]="https://rdap.publicinterestregistry.org/v1/domain/" 33 | 34 | ) 35 | 36 | # Load server cache if exists 37 | [ -f "$CACHE_FILE" ] && source "$CACHE_FILE" 38 | 39 | # Check arguments 40 | [ $# -ne 1 ] && { echo "usage: $0 domain_name"; exit 1; } 41 | domain=$1 42 | tld=${domain##*.} 43 | 44 | # Fast RDAP lookup (for known TLDs) 45 | get_rdap_expiration() { 46 | local url="${RDAP_SERVERS[$tld]}${domain}" 47 | [ -z "$url" ] && return 1 48 | 49 | # Ultra-fast lookup with aggressive timeout 50 | local response=$(curl -s --max-time $RDAP_TIMEOUT -H "Accept: application/rdap+json" "$url" 2>/dev/null) 51 | local expiration=$(echo "$response" | jq -r '.events[]? | select(.eventAction=="expiration") | .eventDate' 2>/dev/null) 52 | 53 | [ -n "$expiration" ] && date -d "$expiration" "+%Y-%m-%d" 2>/dev/null 54 | } 55 | 56 | # Optimized WHOIS lookup 57 | get_whois_expiration() { 58 | local output=$(timeout $WHOIS_TIMEOUT whois "$domain" 2>&1) 59 | echo "$output" | grep -oE 'Expir.*date:[[:space:]]*[0-9-]+|paid-till:[[:space:]]*[0-9-]+' | \ 60 | head -n1 | awk '{print $NF}' | grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2}' 61 | } 62 | 63 | # Main execution flow 64 | { 65 | # 1. First try RDAP if we have a cached server 66 | if [ -n "${RDAP_SERVERS[$tld]}" ]; then 67 | if expiration_date=$(get_rdap_expiration); then 68 | expiration_epoch=$(date -d "$expiration_date" +%s) 69 | echo $(( (expiration_epoch - $(date +%s)) / 86400 )) 70 | exit 0 71 | fi 72 | fi 73 | 74 | # 2. Fall back to WHOIS 75 | if expiration_date=$(get_whois_expiration); then 76 | expiration_epoch=$(date -d "$expiration_date" +%s) 77 | echo $(( (expiration_epoch - $(date +%s)) / 86400 )) 78 | exit 0 79 | fi 80 | 81 | # 3. Final fallback: Try discovering RDAP server 82 | if [ -z "${RDAP_SERVERS[$tld]}" ]; then 83 | # Try common RDAP pattern (only once per TLD) 84 | potential_url="https://rdap.nic.$tld/v1/domain/$domain" 85 | if curl -s --max-time 1 --head "$potential_url" | grep -q "HTTP.*200"; then 86 | RDAP_SERVERS["$tld"]="https://rdap.nic.$tld/v1/domain/" 87 | declare -p RDAP_SERVERS > "$CACHE_FILE" 88 | 89 | if expiration_date=$(get_rdap_expiration); then 90 | expiration_epoch=$(date -d "$expiration_date" +%s) 91 | echo $(( (expiration_epoch - $(date +%s)) / 86400 )) 92 | exit 0 93 | fi 94 | fi 95 | fi 96 | 97 | echo "ERROR: Could not determine expiration date for $domain" 98 | exit 1 99 | } -------------------------------------------------------------------------------- /Template SSL check via file.yaml: -------------------------------------------------------------------------------- 1 | zabbix_export: 2 | version: '6.2' 3 | date: '2023-03-26T10:25:27Z' 4 | template_groups: 5 | - 6 | uuid: 7df96b18c230490a9a0a9e2307226338 7 | name: Templates 8 | templates: 9 | - 10 | uuid: e1faf7238e294603a72bc9a4d02ea960 11 | template: 'Template SSL check via file' 12 | name: 'Template SSL check via file' 13 | groups: 14 | - 15 | name: Templates 16 | discovery_rules: 17 | - 18 | uuid: f144797ab4904691abd6e9bb2b6f2b48 19 | name: 'URLs discovery via file' 20 | type: EXTERNAL 21 | key: 'list.sh["ssl_check.json"]' 22 | delay: 1h 23 | lifetime: 60d 24 | item_prototypes: 25 | - 26 | uuid: 0819c474f68b4b84b6d8cb654a5259c7 27 | name: 'HTTP response code {#URL}:{#PORT}' 28 | type: HTTP_AGENT 29 | key: 'http.response200[{#URL},{#PORT}]' 30 | delay: 5m 31 | history: 10d 32 | trends: 730d 33 | preprocessing: 34 | - 35 | type: REGEX 36 | parameters: 37 | - 'HTTP.*\s(\d+)\s.*' 38 | - \1 39 | url: 'https://{#URL}' 40 | status_codes: '' 41 | retrieve_mode: HEADERS 42 | tags: 43 | - 44 | tag: Application 45 | value: 'HTTPS Service' 46 | trigger_prototypes: 47 | - 48 | uuid: 0a0ea8d05b2145c6a1a1f1b7ae374f5d 49 | expression: 'last(/Template SSL check via file/http.response200[{#URL},{#PORT}])>302' 50 | name: 'HTTP response not equal 200 on {#URL}:{#PORT}' 51 | url: 'https://{#URL}' 52 | priority: AVERAGE 53 | - 54 | uuid: 1a713989d41a4ca692042ee932c1691a 55 | name: 'HTTPS Service on {#URL}:{#PORT} is running' 56 | type: SIMPLE 57 | key: 'net.tcp.service[https,{#URL},{#PORT}]' 58 | delay: 5m 59 | history: 10d 60 | trends: 730d 61 | valuemap: 62 | name: 'Service state' 63 | tags: 64 | - 65 | tag: Application 66 | value: 'HTTPS Service' 67 | trigger_prototypes: 68 | - 69 | uuid: a0630601c5884c3594ca94ebd0dadf30 70 | expression: 'max(/Template SSL check via file/net.tcp.service[https,{#URL},{#PORT}],#3)=0' 71 | name: 'HTTPS service is down on {#URL}:{#PORT}' 72 | priority: AVERAGE 73 | description: | 74 | Last value: {ITEM.LASTVALUE1}. 75 | HTTPS service is down on {#URL}:{#PORT} 76 | - 77 | uuid: 7276f1a300334b98951efdf94d7dc4e5 78 | name: 'SSL certificate validity {#URL}:{#PORT}' 79 | type: EXTERNAL 80 | key: 'zext_ssl_cert.sh[-d,{#URL},{#PORT}]' 81 | delay: 1h 82 | history: 10d 83 | trends: 730d 84 | value_type: FLOAT 85 | units: day(s) 86 | tags: 87 | - 88 | tag: Application 89 | value: 'SSL Checks' 90 | trigger_prototypes: 91 | - 92 | uuid: 5298aa96bb3c41f8b50cca33058bfc3d 93 | expression: 'nodata(/Template SSL check via file/zext_ssl_cert.sh[-d,{#URL},{#PORT}],210m)=1' 94 | name: 'Falied to establish SSL connectoin on {#URL}:{#PORT} in last 3 hour' 95 | status: DISABLED 96 | priority: HIGH 97 | - 98 | uuid: 493e729cb0934497aacb06eb3ab969d7 99 | expression: 'last(/Template SSL check via file/zext_ssl_cert.sh[-d,{#URL},{#PORT}])<0' 100 | name: 'SSL certificate on {#URL}:{#PORT} expired' 101 | priority: DISASTER 102 | - 103 | uuid: 2ff5ca35a92b4ee49150ef59e1e40625 104 | expression: 'last(/Template SSL check via file/zext_ssl_cert.sh[-d,{#URL},{#PORT}])<7' 105 | name: 'SSL certificate on {#URL}:{#PORT} expires in less than 7 days' 106 | priority: HIGH 107 | description: | 108 | Last value: {ITEM.LASTVALUE1}. 109 | SSL certificate on {#URL}:{#PORT} expires in less than week 110 | dependencies: 111 | - 112 | name: 'SSL certificate on {#URL}:{#PORT} expired' 113 | expression: 'last(/Template SSL check via file/zext_ssl_cert.sh[-d,{#URL},{#PORT}])<0' 114 | - 115 | uuid: e04b106554854514ab7b3d821a9a7b57 116 | expression: 'last(/Template SSL check via file/zext_ssl_cert.sh[-d,{#URL},{#PORT}])<21' 117 | name: 'SSL certificate on {#URL}:{#PORT} expires in less than 21 days' 118 | priority: WARNING 119 | description: | 120 | Last value: {ITEM.LASTVALUE1}. 121 | SSL certificate on {#URL}:{#PORT} expires in less than 3 week 122 | dependencies: 123 | - 124 | name: 'SSL certificate on {#URL}:{#PORT} expires in less than 7 days' 125 | expression: 'last(/Template SSL check via file/zext_ssl_cert.sh[-d,{#URL},{#PORT}])<7' 126 | - 127 | uuid: d2bfd23599b54d8bbe9d5680054b24c2 128 | name: 'SSL certificate issuer {#URL}:{#PORT}' 129 | type: EXTERNAL 130 | key: 'zext_ssl_cert.sh[-i,{#URL},{#PORT}]' 131 | delay: 1h 132 | history: 10d 133 | trends: '0' 134 | value_type: CHAR 135 | tags: 136 | - 137 | tag: Application 138 | value: 'SSL Checks' 139 | lld_macro_paths: 140 | - 141 | lld_macro: '{#PORT}' 142 | path: $.port 143 | - 144 | lld_macro: '{#URL}' 145 | path: $.url 146 | valuemaps: 147 | - 148 | uuid: 983c1ae60c2846b8bf99f04375a701cf 149 | name: 'Service state' 150 | mappings: 151 | - 152 | value: '0' 153 | newvalue: Down 154 | - 155 | value: '1' 156 | newvalue: Up 157 | -------------------------------------------------------------------------------- /Template SSL check via url.yaml: -------------------------------------------------------------------------------- 1 | zabbix_export: 2 | version: '6.2' 3 | date: '2023-03-26T10:25:27Z' 4 | template_groups: 5 | - 6 | uuid: 7df96b18c230490a9a0a9e2307226338 7 | name: Templates 8 | templates: 9 | - 10 | uuid: bdd818f56d2a4de9851a7565a0e3480b 11 | template: 'Template SSL check via url' 12 | name: 'Template SSL check via url' 13 | groups: 14 | - 15 | name: Templates 16 | discovery_rules: 17 | - 18 | uuid: 4a7d95de117f4d1fbcd29cb4f7851b36 19 | name: 'URLs discovery via URL' 20 | type: HTTP_AGENT 21 | key: urls_discovery 22 | delay: 1h 23 | lifetime: 60d 24 | item_prototypes: 25 | - 26 | uuid: d32474cee6c74ce8a849ad5d8e6f1881 27 | name: 'HTTP response code {#URL}:{#PORT}' 28 | type: HTTP_AGENT 29 | key: 'http.response200[{#URL},{#PORT}]' 30 | delay: 5m 31 | history: 10d 32 | trends: 730d 33 | preprocessing: 34 | - 35 | type: REGEX 36 | parameters: 37 | - 'HTTP.*\s(\d+)\s.*' 38 | - \1 39 | url: 'https://{#URL}' 40 | status_codes: '' 41 | retrieve_mode: HEADERS 42 | tags: 43 | - 44 | tag: Application 45 | value: 'HTTPS Service' 46 | trigger_prototypes: 47 | - 48 | uuid: 55f56b9f6916436bbc1aad99bbb2d64c 49 | expression: 'last(/Template SSL check via url/http.response200[{#URL},{#PORT}])>302' 50 | name: 'HTTP response not equal 200 on {#URL}:{#PORT}' 51 | url: 'https://{#URL}' 52 | priority: AVERAGE 53 | - 54 | uuid: a9397fed363a409c87cfd324e7452cfb 55 | name: 'HTTPS Service on {#URL}:{#PORT} is running' 56 | type: SIMPLE 57 | key: 'net.tcp.service[https,{#URL},{#PORT}]' 58 | delay: 5m 59 | history: 10d 60 | trends: 730d 61 | valuemap: 62 | name: 'Service state' 63 | tags: 64 | - 65 | tag: Application 66 | value: 'HTTPS Service' 67 | trigger_prototypes: 68 | - 69 | uuid: 7b9bedbfd5dc4781a3e8739f78ab5fa2 70 | expression: 'max(/Template SSL check via url/net.tcp.service[https,{#URL},{#PORT}],#3)=0' 71 | name: 'HTTPS service is down on {#URL}:{#PORT}' 72 | priority: AVERAGE 73 | description: | 74 | Last value: {ITEM.LASTVALUE1}. 75 | HTTPS service is down on {#URL}:{#PORT} 76 | - 77 | uuid: f4b74df735354cd19c511adc0f94adbb 78 | name: 'SSL certificate validity {#URL}:{#PORT}' 79 | type: EXTERNAL 80 | key: 'zext_ssl_cert.sh[-d,{#URL},{#PORT}]' 81 | delay: 1h 82 | history: 10d 83 | trends: 730d 84 | value_type: FLOAT 85 | units: day(s) 86 | tags: 87 | - 88 | tag: Application 89 | value: 'SSL Checks' 90 | trigger_prototypes: 91 | - 92 | uuid: 762f79d63fd947feb8fd6e7aa906f036 93 | expression: 'nodata(/Template SSL check via url/zext_ssl_cert.sh[-d,{#URL},{#PORT}],210m)=1' 94 | name: 'Falied to establish SSL connection on {#URL}:{#PORT} in last 3 hour' 95 | status: DISABLED 96 | priority: HIGH 97 | - 98 | uuid: ce37ee46ef2c4b88b8fc20c024e2ec1d 99 | expression: 'last(/Template SSL check via url/zext_ssl_cert.sh[-d,{#URL},{#PORT}])<0' 100 | name: 'SSL certificate on {#URL}:{#PORT} expired' 101 | priority: DISASTER 102 | - 103 | uuid: 38524bbf247e4e03b0086ac09eecb11c 104 | expression: 'last(/Template SSL check via url/zext_ssl_cert.sh[-d,{#URL},{#PORT}])<7' 105 | name: 'SSL certificate on {#URL}:{#PORT} expires in less than 7 days' 106 | priority: HIGH 107 | description: | 108 | Last value: {ITEM.LASTVALUE1}. 109 | SSL certificate on {#URL}:{#PORT} expires in less than week 110 | dependencies: 111 | - 112 | name: 'SSL certificate on {#URL}:{#PORT} expired' 113 | expression: 'last(/Template SSL check via url/zext_ssl_cert.sh[-d,{#URL},{#PORT}])<0' 114 | - 115 | uuid: 03a8f940f68846c7b19bca34966427f5 116 | expression: 'last(/Template SSL check via url/zext_ssl_cert.sh[-d,{#URL},{#PORT}])<21' 117 | name: 'SSL certificate on {#URL}:{#PORT} expires in less than 21 days' 118 | priority: WARNING 119 | description: | 120 | Last value: {ITEM.LASTVALUE1}. 121 | SSL certificate on {#URL}:{#PORT} expires in less than 3 week 122 | dependencies: 123 | - 124 | name: 'SSL certificate on {#URL}:{#PORT} expires in less than 7 days' 125 | expression: 'last(/Template SSL check via url/zext_ssl_cert.sh[-d,{#URL},{#PORT}])<7' 126 | - 127 | uuid: ebef63dced08458195b370387364cbc6 128 | name: 'SSL certificate issuer {#URL}:{#PORT}' 129 | type: EXTERNAL 130 | key: 'zext_ssl_cert.sh[-i,{#URL},{#PORT}]' 131 | delay: 1h 132 | history: 10d 133 | trends: '0' 134 | value_type: CHAR 135 | tags: 136 | - 137 | tag: Application 138 | value: 'SSL Checks' 139 | url: 'https://raw.githubusercontent.com/kulpin74/zabbix-ssl/master/externalscripts/ssl_check.json' 140 | lld_macro_paths: 141 | - 142 | lld_macro: '{#PORT}' 143 | path: $.port 144 | - 145 | lld_macro: '{#URL}' 146 | path: $.url 147 | valuemaps: 148 | - 149 | uuid: ebef63dced08458195b370387364cbc6 150 | name: 'Service state' 151 | mappings: 152 | - 153 | value: '0' 154 | newvalue: Down 155 | - 156 | value: '1' 157 | newvalue: Up 158 | --------------------------------------------------------------------------------