@@ -118,6 +118,68 @@ func extractCustomQueryParams(c *mysql.Config) (map[string]string, error) {
118
118
}
119
119
120
120
func urlToMySQLConfig (url string ) (* mysql.Config , error ) {
121
+ // Need to parse out custom TLS parameters and call
122
+ // mysql.RegisterTLSConfig() before mysql.ParseDSN() is called
123
+ // which consumes the registered tls.Config
124
+ // Fixes: https://github.com/golang-migrate/migrate/issues/411
125
+ //
126
+ // Can't use url.Parse() since it fails to parse MySQL DSNs
127
+ // mysql.ParseDSN() also searches for "?" to find query parameters:
128
+ // https://github.com/go-sql-driver/mysql/blob/46351a8/dsn.go#L344
129
+ if idx := strings .LastIndex (url , "?" ); idx > 0 {
130
+ rawParams := url [idx + 1 :]
131
+ parsedParams , err := nurl .ParseQuery (rawParams )
132
+ if err != nil {
133
+ return nil , err
134
+ }
135
+
136
+ ctls := parsedParams .Get ("tls" )
137
+ if len (ctls ) > 0 {
138
+ if _ , isBool := readBool (ctls ); ! isBool && strings .ToLower (ctls ) != "skip-verify" {
139
+ rootCertPool := x509 .NewCertPool ()
140
+ pem , err := ioutil .ReadFile (parsedParams .Get ("x-tls-ca" ))
141
+ if err != nil {
142
+ return nil , err
143
+ }
144
+
145
+ if ok := rootCertPool .AppendCertsFromPEM (pem ); ! ok {
146
+ return nil , ErrAppendPEM
147
+ }
148
+
149
+ clientCert := make ([]tls.Certificate , 0 , 1 )
150
+ if ccert , ckey := parsedParams .Get ("x-tls-cert" ), parsedParams .Get ("x-tls-key" ); ccert != "" || ckey != "" {
151
+ if ccert == "" || ckey == "" {
152
+ return nil , ErrTLSCertKeyConfig
153
+ }
154
+ certs , err := tls .LoadX509KeyPair (ccert , ckey )
155
+ if err != nil {
156
+ return nil , err
157
+ }
158
+ clientCert = append (clientCert , certs )
159
+ }
160
+
161
+ insecureSkipVerify := false
162
+ insecureSkipVerifyStr := parsedParams .Get ("x-tls-insecure-skip-verify" )
163
+ if len (insecureSkipVerifyStr ) > 0 {
164
+ x , err := strconv .ParseBool (insecureSkipVerifyStr )
165
+ if err != nil {
166
+ return nil , err
167
+ }
168
+ insecureSkipVerify = x
169
+ }
170
+
171
+ err = mysql .RegisterTLSConfig (ctls , & tls.Config {
172
+ RootCAs : rootCertPool ,
173
+ Certificates : clientCert ,
174
+ InsecureSkipVerify : insecureSkipVerify ,
175
+ })
176
+ if err != nil {
177
+ return nil , err
178
+ }
179
+ }
180
+ }
181
+ }
182
+
121
183
config , err := mysql .ParseDSN (strings .TrimPrefix (url , "mysql://" ))
122
184
if err != nil {
123
185
return nil , err
@@ -140,52 +202,6 @@ func urlToMySQLConfig(url string) (*mysql.Config, error) {
140
202
}
141
203
config .Passwd = password
142
204
143
- // use custom TLS?
144
- ctls := config .TLSConfig
145
- if len (ctls ) > 0 {
146
- if _ , isBool := readBool (ctls ); ! isBool && strings .ToLower (ctls ) != "skip-verify" {
147
- rootCertPool := x509 .NewCertPool ()
148
- pem , err := ioutil .ReadFile (config .Params ["x-tls-ca" ])
149
- if err != nil {
150
- return nil , err
151
- }
152
-
153
- if ok := rootCertPool .AppendCertsFromPEM (pem ); ! ok {
154
- return nil , ErrAppendPEM
155
- }
156
-
157
- clientCert := make ([]tls.Certificate , 0 , 1 )
158
- if ccert , ckey := config .Params ["x-tls-cert" ], config .Params ["x-tls-key" ]; ccert != "" || ckey != "" {
159
- if ccert == "" || ckey == "" {
160
- return nil , ErrTLSCertKeyConfig
161
- }
162
- certs , err := tls .LoadX509KeyPair (ccert , ckey )
163
- if err != nil {
164
- return nil , err
165
- }
166
- clientCert = append (clientCert , certs )
167
- }
168
-
169
- insecureSkipVerify := false
170
- if len (config .Params ["x-tls-insecure-skip-verify" ]) > 0 {
171
- x , err := strconv .ParseBool (config .Params ["x-tls-insecure-skip-verify" ])
172
- if err != nil {
173
- return nil , err
174
- }
175
- insecureSkipVerify = x
176
- }
177
-
178
- err = mysql .RegisterTLSConfig (ctls , & tls.Config {
179
- RootCAs : rootCertPool ,
180
- Certificates : clientCert ,
181
- InsecureSkipVerify : insecureSkipVerify ,
182
- })
183
- if err != nil {
184
- return nil , err
185
- }
186
- }
187
- }
188
-
189
205
return config , nil
190
206
}
191
207
0 commit comments