Commit ce43513e authored by jaloren's avatar jaloren Committed by Ben Kochie

Support custom CA truststore and client SSL keypair. (#255)

Per discussion in #226, there is no way to specify a custom CA that the
mysqld exporter will trust when establishing a SSL connection to a mysql
server. So if a mysql server has a custom truststore, an operator would
need to set DSN, where tls=skip-verify.

With this change, a user can define the ssl options in the mysql cnf and
then the mysqld exporter will construct a DSN and a custom TLS config
based on those options.
parent 8f657848
......@@ -102,6 +102,24 @@ The MySQL server's [data source name](
must be set via the `DATA_SOURCE_NAME` environment variable.
The format of this variable is described at
## Customizing Configuration for a SSL Connection
if The MySQL server supports SSL, you may need to specify a CA truststore to verify the server's chain-of-trust. You may also need to specify a SSL keypair for the client side of the SSL connection. To configure the mysqld exporter to use a custom CA certificate, add the following to the mysql cnf file:
To specify the client SSL keypair, add the following to the cnf.
Customizing the SSL configuration is only supported in the mysql cnf file and is not supported if you set the mysql server's data source name in the environment variable DATA_SOURCE_NAME.
## Using Docker
You can deploy this exporter using the [prom/mysqld-exporter]( Docker image.
package main
import (
......@@ -86,10 +90,47 @@ func parseMycnf(config interface{}) (string, error) {
} else {
dsn = fmt.Sprintf("%s:%s@tcp(%s:%d)/", user, password, host, port)
sslCA := cfg.Section("client").Key("ssl-ca").String()
sslCert := cfg.Section("client").Key("ssl-cert").String()
sslKey := cfg.Section("client").Key("ssl-key").String()
if sslCA != "" {
if tlsErr := customizeTLS(sslCA, sslCert, sslKey); tlsErr != nil {
tlsErr = fmt.Errorf("failed to register a custom TLS configuration for mysql dsn: %s", tlsErr)
return dsn, tlsErr
dsn = fmt.Sprintf("%s?tls=custom", dsn)
return dsn, nil
func customizeTLS(sslCA string, sslCert string, sslKey string) error {
var tlsCfg tls.Config
caBundle := x509.NewCertPool()
pemCA, err := ioutil.ReadFile(sslCA)
if err != nil {
return err
if ok := caBundle.AppendCertsFromPEM(pemCA); ok {
tlsCfg.RootCAs = caBundle
} else {
return fmt.Errorf("failed parse pem-encoded CA certificates from %s", sslCA)
if sslCert != "" && sslKey != "" {
certPairs := make([]tls.Certificate, 0, 1)
keypair, err := tls.LoadX509KeyPair(sslCert, sslKey)
if err != nil {
return fmt.Errorf("failed to parse pem-encoded SSL cert %s or SSL key %s: %s",
sslCert, sslKey, err)
certPairs = append(certPairs, keypair)
tlsCfg.Certificates = certPairs
mysql.RegisterTLSConfig("custom", &tlsCfg)
return nil
func init() {
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment