go-sql-driver / mysql

Go MySQL Driver is a MySQL driver for Go's (golang) database/sql package
https://pkg.go.dev/github.com/go-sql-driver/mysql
Mozilla Public License 2.0
14.45k stars 2.3k forks source link

Provide Client TLS Certificates as Query Parameters #1611

Open nickzelei opened 1 month ago

nickzelei commented 1 month ago

Issue description

I'd like to be able to provide SSL certificate paths via query parameters in the DSN instead of explicitly registering them with the driver.

I need to do this because I'm operating a service that runs in a multi-tenant environment and I don't want to have to register these in a global way, but instead provide them as paths.

It's possible I'm just doing something stupid here and just can't see it, but I get an error when trying to provide them as query parameters.

This seems to be possible when looking at the supported connection parameters: https://dev.mysql.com/doc/refman/8.0/en/connecting-using-uri-or-key-value-pairs.html

ssl-ca: The path to the X.509 certificate authority file in PEM format.
ssl-capath: The path to the directory that contains the X.509 certificates authority files in PEM format.
ssl-cert: The path to the X.509 certificate file in PEM format.
ssl-cipher: The encryption cipher to use for connections that use TLS protocols up through TLSv1.2.
ssl-crl: The path to the file that contains certificate revocation lists in PEM format.
ssl-crlpath: The path to the directory that contains certificate revocation-list files in PEM format.
ssl-key: The path to the X.509 key file in PEM format.

Example code

https://gist.github.com/nickzelei/cab80c7424a2d7099ce0663ed6e9f6d4

Relevant snippet

    caCertPath := url.QueryEscape("/Users/nick/code/dbssl/certs/root.crt")
    clientCertPath := url.QueryEscape("/Users/nick/code/dbssl/certs/client.crt")
    clientKeyPath := url.QueryEscape("/Users/nick/code/dbssl/certs/client.key")
    tls := url.QueryEscape("skip-verify")

    dsn := fmt.Sprintf("myuser:mypassword@tcp(localhost:3306)/mydb?tls=%s&ssl-ca=%s&ssl-cert=%s&ssl-key=%s&timeout=5s",
        tls, caCertPath, clientCertPath, clientKeyPath)

Error log

2024/07/19 10:02:49 Error pinging database: Error 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ssl-ca = /Users/nick/code/dbssl/certs/root.crt, ssl-cert' at line 1
exit status 1

Configuration

Driver version: v1.8.1

Go version: go version go1.22.5 darwin/arm64

Server version: MySQL 8.0 (official docker image)