From 9905791932573b134e204cfd408e38a1a601e4e5 Mon Sep 17 00:00:00 2001 From: Tatsuhito KATO Date: Mon, 13 Aug 2018 11:43:19 +0000 Subject: [PATCH 1/4] Fixes MySQL custom TLS connection failure. --- database/mysql/README.md | 1 + database/mysql/mysql.go | 30 +++++++++++++++++------------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/database/mysql/README.md b/database/mysql/README.md index 0cb1299..636cb53 100644 --- a/database/mysql/README.md +++ b/database/mysql/README.md @@ -10,6 +10,7 @@ | `password` | | The user's password | | `host` | | The host to connect to. | | `port` | | The port to bind to. | +| `tls` | | The custom TLS config name, use with `x-tls-` queries. | | `x-tls-ca` | | The location of the root certificate file. | | `x-tls-cert` | | Cert file location. | | `x-tls-key` | | Key file location. | diff --git a/database/mysql/mysql.go b/database/mysql/mysql.go index 85afbfa..504df33 100644 --- a/database/mysql/mysql.go +++ b/database/mysql/mysql.go @@ -123,15 +123,6 @@ func (m *Mysql) Open(url string) (database.Driver, error) { q.Set("multiStatements", "true") purl.RawQuery = q.Encode() - c, err := urlToMySQLConfig(*migrate.FilterCustomQuery(purl)) - if err != nil { - return nil, err - } - db, err := sql.Open("mysql", c.FormatDSN()) - if err != nil { - return nil, err - } - migrationsTable := purl.Query().Get("x-migrations-table") if len(migrationsTable) == 0 { migrationsTable = DefaultMigrationsTable @@ -151,9 +142,13 @@ func (m *Mysql) Open(url string) (database.Driver, error) { return nil, ErrAppendPEM } - certs, err := tls.LoadX509KeyPair(purl.Query().Get("x-tls-cert"), purl.Query().Get("x-tls-key")) - if err != nil { - return nil, err + clientCert := make([]tls.Certificate, 0, 1) + if purl.Query().Get("x-tls-cert") != "" && purl.Query().Get("x-tls-key") != "" { + certs, err := tls.LoadX509KeyPair(purl.Query().Get("x-tls-cert"), purl.Query().Get("x-tls-key")) + if err != nil { + return nil, err + } + clientCert = append(clientCert, certs) } insecureSkipVerify := false @@ -167,12 +162,21 @@ func (m *Mysql) Open(url string) (database.Driver, error) { mysql.RegisterTLSConfig(ctls, &tls.Config{ RootCAs: rootCertPool, - Certificates: []tls.Certificate{certs}, + Certificates: clientCert, InsecureSkipVerify: insecureSkipVerify, }) } } + c, err := urlToMySQLConfig(*migrate.FilterCustomQuery(purl)) + if err != nil { + return nil, err + } + db, err := sql.Open("mysql", c.FormatDSN()) + if err != nil { + return nil, err + } + mx, err := WithInstance(db, &Config{ DatabaseName: purl.Path, MigrationsTable: migrationsTable, From 9d36dd9841a6a9e6058dc93b1080e17524187edd Mon Sep 17 00:00:00 2001 From: Tatsuhito KATO Date: Tue, 14 Aug 2018 07:42:10 +0000 Subject: [PATCH 2/4] Add detail of `tls` query. --- database/mysql/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/mysql/README.md b/database/mysql/README.md index 636cb53..e9a0b7c 100644 --- a/database/mysql/README.md +++ b/database/mysql/README.md @@ -10,7 +10,7 @@ | `password` | | The user's password | | `host` | | The host to connect to. | | `port` | | The port to bind to. | -| `tls` | | The custom TLS config name, use with `x-tls-` queries. | +| `tls` | | TLS / SSL encrypted connection parameter; see [go-sql-driver](https://github.com/go-sql-driver/mysql#tls). Use any name (e.g. `migrate`) if you want to use a custom TLS config (`x-tls-` queries). | | `x-tls-ca` | | The location of the root certificate file. | | `x-tls-cert` | | Cert file location. | | `x-tls-key` | | Key file location. | From 9049e49f9ededa87313960bfd4d9f0a52b6b994e Mon Sep 17 00:00:00 2001 From: Tatsuhito KATO Date: Tue, 14 Aug 2018 07:43:14 +0000 Subject: [PATCH 3/4] `x-tls-cert` and `x-tls-key` must set both. --- database/mysql/mysql.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/mysql/mysql.go b/database/mysql/mysql.go index 504df33..7d66139 100644 --- a/database/mysql/mysql.go +++ b/database/mysql/mysql.go @@ -143,8 +143,8 @@ func (m *Mysql) Open(url string) (database.Driver, error) { } clientCert := make([]tls.Certificate, 0, 1) - if purl.Query().Get("x-tls-cert") != "" && purl.Query().Get("x-tls-key") != "" { - certs, err := tls.LoadX509KeyPair(purl.Query().Get("x-tls-cert"), purl.Query().Get("x-tls-key")) + if ccert, ckey := purl.Query().Get("x-tls-cert"), purl.Query().Get("x-tls-key"); ccert != "" || ckey != "" { + certs, err := tls.LoadX509KeyPair(ccert, ckey) if err != nil { return nil, err } From 02c83fb38b897074fa18cae548635294cc0368ed Mon Sep 17 00:00:00 2001 From: Tatsuhito KATO Date: Wed, 15 Aug 2018 02:42:18 +0000 Subject: [PATCH 4/4] more descriptive. --- database/mysql/README.md | 6 +++--- database/mysql/mysql.go | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/database/mysql/README.md b/database/mysql/README.md index e9a0b7c..d0b908d 100644 --- a/database/mysql/README.md +++ b/database/mysql/README.md @@ -11,9 +11,9 @@ | `host` | | The host to connect to. | | `port` | | The port to bind to. | | `tls` | | TLS / SSL encrypted connection parameter; see [go-sql-driver](https://github.com/go-sql-driver/mysql#tls). Use any name (e.g. `migrate`) if you want to use a custom TLS config (`x-tls-` queries). | -| `x-tls-ca` | | The location of the root certificate file. | -| `x-tls-cert` | | Cert file location. | -| `x-tls-key` | | Key file location. | +| `x-tls-ca` | | The location of the CA (certificate authority) file. | +| `x-tls-cert` | | The location of the client certicicate file. Must be used with `x-tls-key`. | +| `x-tls-key` | | The location of the private key file. Must be used with `x-tls-cert`. | | `x-tls-insecure-skip-verify` | | Whether or not to use SSL (true\|false) | ## Use with existing client diff --git a/database/mysql/mysql.go b/database/mysql/mysql.go index 7d66139..323edae 100644 --- a/database/mysql/mysql.go +++ b/database/mysql/mysql.go @@ -35,6 +35,7 @@ var ( ErrNilConfig = fmt.Errorf("no config") ErrNoDatabaseName = fmt.Errorf("no database name") ErrAppendPEM = fmt.Errorf("failed to append PEM") + ErrTLSCertKeyConfig = fmt.Errorf("To use TLS client authentication, both x-tls-cert and x-tls-key must not be empty") ) type Config struct { @@ -144,6 +145,9 @@ func (m *Mysql) Open(url string) (database.Driver, error) { clientCert := make([]tls.Certificate, 0, 1) if ccert, ckey := purl.Query().Get("x-tls-cert"), purl.Query().Get("x-tls-key"); ccert != "" || ckey != "" { + if ccert == "" || ckey == "" { + return nil, ErrTLSCertKeyConfig + } certs, err := tls.LoadX509KeyPair(ccert, ckey) if err != nil { return nil, err