Check mysql-tls¶
Overview¶
Checks MySQL/MariaDB TLS/SSL posture: the current connection itself, the server’s TLS capability (have_ssl), enforcement (require_secure_transport), enabled TLS versions (no TLSv1.0/1.1, at least TLSv1.2 or TLSv1.3), the presence of a server certificate and key, the local expiry of ssl_cert and ssl_ca files (when readable on the same host), and any remote accounts that can still connect without REQUIRE SSL. Logic taken from MySQLTuner:ssl_tls_recommendations(), check_local_certificates() and check_remote_user_ssl(), verified in sync with MySQLTuner.
Important Notes:
The session-cipher check reflects the current connection only. To verify it, configure SSL in the monitoring
.my.cnf(for examplessl=trueorssl-ca=/etc/pki/tls/certs/ca.crt) sopymysqlnegotiates TLSThe local certificate expiry check is silently skipped when the file path is empty. When the path is set but the file is missing or unreadable (typical for a remote monitoring host), the plugin reports „expiry check skipped“ without raising an alert
The local certificate expiry check requires the Python
cryptographymodule; if it is not installed the check is skipped with a clear reason and no alertmysqltuner’s local-cert audit only checks
ssl_certandssl_ca(notssl_key); we follow the same scope - no key match, no CN/SAN checkThe remote-user check uses the same host filter as mysqltuner (
host NOT IN ('localhost', '127.0.0.1', '::1')) and readsmysql.global_privon MariaDB 10.4+ andmysql.user.ssl_typeotherwise
Data Collection:
Reads
SHOW GLOBAL VARIABLESonce forhave_ssl,require_secure_transport,tls_version,ssl_cert,ssl_key,ssl_caandversionReads
SHOW SESSION STATUS LIKE 'Ssl_cipher'to detect whether the current connection is encryptedQueries
mysql.user(ormysql.global_privon MariaDB 10.4+) for remote accounts withoutREQUIRE SSLReads the
ssl_certandssl_cafiles via thecryptographyPython module to derive the days until expiry, when the files are locally readable
Fact Sheet¶
Fact |
Value |
|---|---|
Check Plugin Download |
https://github.com/Linuxfabrik/monitoring-plugins/tree/main/check-plugins/mysql-tls |
Nagios/Icinga Check Name |
|
Check Interval Recommendation |
Every hour |
Can be called without parameters |
Yes |
Runs on |
Cross-platform |
Compiled for Windows |
No |
Requirements |
User with |
3rd Party Python modules |
|
Help¶
usage: mysql-tls [-h] [-V] [--always-ok] [-c CRIT]
[--defaults-file DEFAULTS_FILE]
[--defaults-group DEFAULTS_GROUP] [--severity {warn,crit}]
[--timeout TIMEOUT] [-w WARN]
Checks MySQL/MariaDB TLS/SSL posture: the current connection itself, the
server's TLS capability (`have_ssl`), enforcement
(`require_secure_transport`), enabled TLS versions (no TLSv1.0/1.1, at least
TLSv1.2 or TLSv1.3), the presence of a server certificate and key, the local
expiry of `ssl_cert` and `ssl_ca` files (when readable on the same host), and
any remote accounts that can still connect without `REQUIRE SSL`. Each finding
maps to a copy-pasteable SQL or `openssl` recommendation.
options:
-h, --help show this help message and exit
-V, --version show program's version number and exit
--always-ok Always returns OK.
-c, --critical CRIT Days until local `ssl_cert` / `ssl_ca` expiry that
trigger CRIT. Supports Nagios ranges. Example:
`--critical=14:`. Default: 7:
--defaults-file DEFAULTS_FILE
MySQL/MariaDB cnf file to read user, host and password
from. Example: `--defaults-
file=/var/spool/icinga2/.my.cnf`. Default:
/var/spool/icinga2/.my.cnf
--defaults-group DEFAULTS_GROUP
Group/section to read from in the cnf file. Default:
client
--severity {warn,crit}
Severity for the threshold-less TLS findings (session
not encrypted, `have_ssl=DISABLED`,
`require_secure_transport=OFF`, weak TLS versions,
missing cert/key, remote users without `REQUIRE SSL`).
One of `warn` or `crit`. Default: warn
--timeout TIMEOUT Network timeout in seconds. Default: 3 (seconds)
-w, --warning WARN Days until local `ssl_cert` / `ssl_ca` expiry that
trigger WARN. Supports Nagios ranges. Example:
`--warning=60:`. Default: 30:
Usage Examples¶
./mysql-tls --defaults-file=/var/spool/icinga2/.my.cnf
OK output:
Everything is ok. Current connection encrypted (TLS_AES_256_GCM_SHA384). `have_ssl` enabled. `require_secure_transport` = ON. TLS versions: TLSv1.2, TLSv1.3. `ssl_cert` (/etc/mysql/ssl/server.pem) expires in 318d. `ssl_ca` (/etc/mysql/ssl/ca.pem) expires in 1825d. 0 remote users without `REQUIRE SSL`.
WARN output:
Current connection not encrypted [WARNING]. `have_ssl` enabled. `require_secure_transport` = OFF [WARNING]. 1 insecure TLS version enabled (in `TLSv1.1, TLSv1.2, TLSv1.3`) [WARNING]. `ssl_cert` (/etc/mysql/ssl/server.pem) expires in 12d [WARNING]. `ssl_ca` (/etc/mysql/ssl/ca.pem) expiry check skipped (file not readable: /etc/mysql/ssl/ca.pem). 2 remote users without `REQUIRE SSL` [WARNING].
Recommendations:
* Add `ssl=true` (or `ssl-ca=...`) to the [client] section of the monitoring `.my.cnf`, and ensure the server is reachable over TLS.
* `SET GLOBAL require_secure_transport = 'ON';`
* Persist `require_secure_transport = ON` in the server config so the setting survives restarts.
* Set `tls_version=TLSv1.2,TLSv1.3` in your server config and restart the service.
* Renew `ssl_cert` (/etc/mysql/ssl/server.pem) and reload the server.
* `ALTER USER 'app'@'10.%' REQUIRE SSL;`
* `ALTER USER 'replica'@'10.0.0.5' REQUIRE SSL;`
States¶
OK if every finding passes.
--severity warn(default) or--severity critcontrols the state returned for each of the threshold-less findings (session not encrypted,have_ssl=DISABLED,require_secure_transport=OFF, weak TLS versions, missing cert/key, remote users withoutREQUIRE SSL).The local certificate expiry check has its own thresholds via
--warning/--critical(Nagios ranges, defaults30:warn /7:crit). An already-expired certificate is always CRIT.--always-oksuppresses all alerts and always returns OK.
Perfdata / Metrics¶
Name |
Type |
Description |
|---|---|---|
mysql_tls_have_ssl |
Number (0/1) |
|
mysql_tls_modern_protocol_versions |
Number |
Count of modern TLS versions enabled in |
mysql_tls_remote_users_without_ssl |
Number |
Count of accounts on a non-localhost host that can connect without |
mysql_tls_required |
Number (0/1) |
|
mysql_tls_session_encrypted |
Number (0/1) |
|
mysql_tls_ssl_ca_days_until_expiry |
Number (d) |
Days until the local |
mysql_tls_ssl_cert_days_until_expiry |
Number (d) |
Days until the local |
mysql_tls_weak_protocol_versions |
Number |
Count of insecure TLS versions enabled in |
Credits, License¶
Authors: Linuxfabrik GmbH, Zurich
License: The Unlicense, see LICENSE file.
Credits:
heavily inspired by MySQLTuner (https://github.com/major/MySQLTuner-perl)