github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/allegrosql/server/mdb_test.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 //go:build !race 14 // +build !race 15 16 package server 17 18 import ( 19 "context" 20 "crypto/rand" 21 "crypto/rsa" 22 "crypto/tls" 23 "crypto/x509" 24 "crypto/x509/pkix" 25 "encoding/pem" 26 "io/ioutil" 27 "math/big" 28 "net/http" 29 "os" 30 "path/filepath" 31 "time" 32 33 "github.com/go-allegrosql-driver/allegrosql" 34 tmysql "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 35 . "github.com/whtcorpsinc/check" 36 "github.com/whtcorpsinc/errors" 37 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 38 "github.com/whtcorpsinc/milevadb/config" 39 "github.com/whtcorpsinc/milevadb/ekv" 40 "github.com/whtcorpsinc/milevadb/metrics" 41 "github.com/whtcorpsinc/milevadb/petri" 42 "github.com/whtcorpsinc/milevadb/soliton" 43 "github.com/whtcorpsinc/milevadb/soliton/testkit" 44 "github.com/whtcorpsinc/milevadb/stochastik" 45 ) 46 47 type milevadbTestSuite struct { 48 *milevadbTestSuiteBase 49 } 50 51 type milevadbTestSerialSuite struct { 52 *milevadbTestSuiteBase 53 } 54 55 type milevadbTestSuiteBase struct { 56 *testServerClient 57 milevadbdrv *MilevaDBDriver 58 server *Server 59 petri *petri.Petri 60 causetstore ekv.CausetStorage 61 } 62 63 func newMilevaDBTestSuiteBase() *milevadbTestSuiteBase { 64 return &milevadbTestSuiteBase{ 65 testServerClient: newTestServerClient(), 66 } 67 } 68 69 var _ = Suite(&milevadbTestSuite{newMilevaDBTestSuiteBase()}) 70 var _ = SerialSuites(&milevadbTestSerialSuite{newMilevaDBTestSuiteBase()}) 71 72 func (ts *milevadbTestSuite) SetUpSuite(c *C) { 73 metrics.RegisterMetrics() 74 ts.milevadbTestSuiteBase.SetUpSuite(c) 75 } 76 77 func (ts *milevadbTestSuiteBase) SetUpSuite(c *C) { 78 var err error 79 ts.causetstore, err = mockstore.NewMockStore() 80 stochastik.DisableStats4Test() 81 c.Assert(err, IsNil) 82 ts.petri, err = stochastik.BootstrapStochastik(ts.causetstore) 83 c.Assert(err, IsNil) 84 ts.milevadbdrv = NewMilevaDBDriver(ts.causetstore) 85 cfg := newTestConfig() 86 cfg.Port = ts.port 87 cfg.Status.ReportStatus = true 88 cfg.Status.StatusPort = ts.statusPort 89 cfg.Performance.TCPKeepAlive = true 90 91 server, err := NewServer(cfg, ts.milevadbdrv) 92 c.Assert(err, IsNil) 93 ts.port = getPortFromTCPAddr(server.listener.Addr()) 94 ts.statusPort = getPortFromTCPAddr(server.statusListener.Addr()) 95 ts.server = server 96 go ts.server.Run() 97 ts.waitUntilServerOnline() 98 } 99 100 func (ts *milevadbTestSuiteBase) TearDownSuite(c *C) { 101 if ts.causetstore != nil { 102 ts.causetstore.Close() 103 } 104 if ts.petri != nil { 105 ts.petri.Close() 106 } 107 if ts.server != nil { 108 ts.server.Close() 109 } 110 } 111 112 func (ts *milevadbTestSuite) TestRegression(c *C) { 113 if regression { 114 c.Parallel() 115 ts.runTestRegression(c, nil, "Regression") 116 } 117 } 118 119 func (ts *milevadbTestSuite) TestUint64(c *C) { 120 ts.runTestPrepareResultFieldType(c) 121 } 122 123 func (ts *milevadbTestSuite) TestSpecialType(c *C) { 124 c.Parallel() 125 ts.runTestSpecialType(c) 126 } 127 128 func (ts *milevadbTestSuite) TestPreparedString(c *C) { 129 c.Parallel() 130 ts.runTestPreparedString(c) 131 } 132 133 func (ts *milevadbTestSuite) TestPreparedTimestamp(c *C) { 134 c.Parallel() 135 ts.runTestPreparedTimestamp(c) 136 } 137 138 // this test will change `ekv.TxnTotalSizeLimit` which may affect other test suites, 139 // so we must make it running in serial. 140 func (ts *milevadbTestSerialSuite) TestLoadData(c *C) { 141 ts.runTestLoadData(c, ts.server) 142 ts.runTestLoadDataWithSelectIntoOutfile(c, ts.server) 143 } 144 145 func (ts *milevadbTestSerialSuite) TestStmtCount(c *C) { 146 ts.runTestStmtCount(c) 147 } 148 149 func (ts *milevadbTestSuite) TestConcurrentUFIDelate(c *C) { 150 c.Parallel() 151 ts.runTestConcurrentUFIDelate(c) 152 } 153 154 func (ts *milevadbTestSuite) TestErrorCode(c *C) { 155 c.Parallel() 156 ts.runTestErrorCode(c) 157 } 158 159 func (ts *milevadbTestSuite) TestAuth(c *C) { 160 c.Parallel() 161 ts.runTestAuth(c) 162 ts.runTestIssue3682(c) 163 } 164 165 func (ts *milevadbTestSuite) TestIssues(c *C) { 166 c.Parallel() 167 ts.runTestIssue3662(c) 168 ts.runTestIssue3680(c) 169 } 170 171 func (ts *milevadbTestSuite) TestDBNameEscape(c *C) { 172 c.Parallel() 173 ts.runTestDBNameEscape(c) 174 } 175 176 func (ts *milevadbTestSuite) TestResultFieldBlockIsNull(c *C) { 177 c.Parallel() 178 ts.runTestResultFieldBlockIsNull(c) 179 } 180 181 func (ts *milevadbTestSuite) TestStatusAPI(c *C) { 182 c.Parallel() 183 ts.runTestStatusAPI(c) 184 } 185 186 func (ts *milevadbTestSuite) TestStatusPort(c *C) { 187 var err error 188 ts.causetstore, err = mockstore.NewMockStore() 189 stochastik.DisableStats4Test() 190 c.Assert(err, IsNil) 191 ts.petri, err = stochastik.BootstrapStochastik(ts.causetstore) 192 c.Assert(err, IsNil) 193 ts.milevadbdrv = NewMilevaDBDriver(ts.causetstore) 194 cfg := newTestConfig() 195 cfg.Port = 0 196 cfg.Status.ReportStatus = true 197 cfg.Status.StatusPort = ts.statusPort 198 cfg.Performance.TCPKeepAlive = true 199 200 server, err := NewServer(cfg, ts.milevadbdrv) 201 c.Assert(err, NotNil) 202 c.Assert(server, IsNil) 203 } 204 205 func (ts *milevadbTestSuite) TestStatusAPIWithTLS(c *C) { 206 caCert, caKey, err := generateCert(0, "MilevaDB CA 2", nil, nil, "/tmp/ca-key-2.pem", "/tmp/ca-cert-2.pem") 207 c.Assert(err, IsNil) 208 _, _, err = generateCert(1, "milevadb-server-2", caCert, caKey, "/tmp/server-key-2.pem", "/tmp/server-cert-2.pem") 209 c.Assert(err, IsNil) 210 211 defer func() { 212 os.Remove("/tmp/ca-key-2.pem") 213 os.Remove("/tmp/ca-cert-2.pem") 214 os.Remove("/tmp/server-key-2.pem") 215 os.Remove("/tmp/server-cert-2.pem") 216 }() 217 218 cli := newTestServerClient() 219 cli.statusScheme = "https" 220 cfg := newTestConfig() 221 cfg.Port = cli.port 222 cfg.Status.StatusPort = cli.statusPort 223 cfg.Security.ClusterSSLCA = "/tmp/ca-cert-2.pem" 224 cfg.Security.ClusterSSLCert = "/tmp/server-cert-2.pem" 225 cfg.Security.ClusterSSLKey = "/tmp/server-key-2.pem" 226 server, err := NewServer(cfg, ts.milevadbdrv) 227 c.Assert(err, IsNil) 228 cli.port = getPortFromTCPAddr(server.listener.Addr()) 229 cli.statusPort = getPortFromTCPAddr(server.statusListener.Addr()) 230 go server.Run() 231 time.Sleep(time.Millisecond * 100) 232 233 // https connection should work. 234 ts.runTestStatusAPI(c) 235 236 // but plain http connection should fail. 237 cli.statusScheme = "http" 238 _, err = cli.fetchStatus("/status") 239 c.Assert(err, NotNil) 240 241 server.Close() 242 } 243 244 func (ts *milevadbTestSuite) TestStatusAPIWithTLSCNCheck(c *C) { 245 caPath := filepath.Join(os.TemFIDelir(), "ca-cert-cn.pem") 246 serverKeyPath := filepath.Join(os.TemFIDelir(), "server-key-cn.pem") 247 serverCertPath := filepath.Join(os.TemFIDelir(), "server-cert-cn.pem") 248 client1KeyPath := filepath.Join(os.TemFIDelir(), "client-key-cn-check-a.pem") 249 client1CertPath := filepath.Join(os.TemFIDelir(), "client-cert-cn-check-a.pem") 250 client2KeyPath := filepath.Join(os.TemFIDelir(), "client-key-cn-check-b.pem") 251 client2CertPath := filepath.Join(os.TemFIDelir(), "client-cert-cn-check-b.pem") 252 253 caCert, caKey, err := generateCert(0, "MilevaDB CA CN CHECK", nil, nil, filepath.Join(os.TemFIDelir(), "ca-key-cn.pem"), caPath) 254 c.Assert(err, IsNil) 255 _, _, err = generateCert(1, "milevadb-server-cn-check", caCert, caKey, serverKeyPath, serverCertPath) 256 c.Assert(err, IsNil) 257 _, _, err = generateCert(2, "milevadb-client-cn-check-a", caCert, caKey, client1KeyPath, client1CertPath, func(c *x509.Certificate) { 258 c.Subject.CommonName = "milevadb-client-1" 259 }) 260 c.Assert(err, IsNil) 261 _, _, err = generateCert(3, "milevadb-client-cn-check-b", caCert, caKey, client2KeyPath, client2CertPath, func(c *x509.Certificate) { 262 c.Subject.CommonName = "milevadb-client-2" 263 }) 264 c.Assert(err, IsNil) 265 266 cli := newTestServerClient() 267 cli.statusScheme = "https" 268 cfg := newTestConfig() 269 cfg.Port = cli.port 270 cfg.Status.StatusPort = cli.statusPort 271 cfg.Security.ClusterSSLCA = caPath 272 cfg.Security.ClusterSSLCert = serverCertPath 273 cfg.Security.ClusterSSLKey = serverKeyPath 274 cfg.Security.ClusterVerifyCN = []string{"milevadb-client-2"} 275 server, err := NewServer(cfg, ts.milevadbdrv) 276 c.Assert(err, IsNil) 277 cli.port = getPortFromTCPAddr(server.listener.Addr()) 278 cli.statusPort = getPortFromTCPAddr(server.statusListener.Addr()) 279 go server.Run() 280 time.Sleep(time.Millisecond * 100) 281 282 hc := newTLSHttpClient(c, caPath, 283 client1CertPath, 284 client1KeyPath, 285 ) 286 _, err = hc.Get(cli.statusURL("/status")) 287 c.Assert(err, NotNil) 288 289 hc = newTLSHttpClient(c, caPath, 290 client2CertPath, 291 client2KeyPath, 292 ) 293 _, err = hc.Get(cli.statusURL("/status")) 294 c.Assert(err, IsNil) 295 } 296 297 func newTLSHttpClient(c *C, caFile, certFile, keyFile string) *http.Client { 298 cert, err := tls.LoadX509KeyPair(certFile, keyFile) 299 c.Assert(err, IsNil) 300 caCert, err := ioutil.ReadFile(caFile) 301 c.Assert(err, IsNil) 302 caCertPool := x509.NewCertPool() 303 caCertPool.AppendCertsFromPEM(caCert) 304 tlsConfig := &tls.Config{ 305 Certificates: []tls.Certificate{cert}, 306 RootCAs: caCertPool, 307 InsecureSkipVerify: true, 308 } 309 tlsConfig.BuildNameToCertificate() 310 return &http.Client{Transport: &http.Transport{TLSClientConfig: tlsConfig}} 311 } 312 313 func (ts *milevadbTestSuite) TestMultiStatements(c *C) { 314 c.Parallel() 315 ts.runTestMultiStatements(c) 316 } 317 318 func (ts *milevadbTestSuite) TestSocketForwarding(c *C) { 319 cli := newTestServerClient() 320 cfg := newTestConfig() 321 cfg.Socket = "/tmp/milevadbtest.sock" 322 cfg.Port = cli.port 323 os.Remove(cfg.Socket) 324 cfg.Status.ReportStatus = false 325 326 server, err := NewServer(cfg, ts.milevadbdrv) 327 c.Assert(err, IsNil) 328 cli.port = getPortFromTCPAddr(server.listener.Addr()) 329 go server.Run() 330 time.Sleep(time.Millisecond * 100) 331 defer server.Close() 332 333 cli.runTestRegression(c, func(config *allegrosql.Config) { 334 config.User = "root" 335 config.Net = "unix" 336 config.Addr = "/tmp/milevadbtest.sock" 337 config.DBName = "test" 338 config.Params = map[string]string{"sql_mode": "'STRICT_ALL_TABLES'"} 339 }, "SocketRegression") 340 } 341 342 func (ts *milevadbTestSuite) TestSocket(c *C) { 343 cfg := newTestConfig() 344 cfg.Socket = "/tmp/milevadbtest.sock" 345 cfg.Port = 0 346 os.Remove(cfg.Socket) 347 cfg.Host = "" 348 cfg.Status.ReportStatus = false 349 350 server, err := NewServer(cfg, ts.milevadbdrv) 351 c.Assert(err, IsNil) 352 go server.Run() 353 time.Sleep(time.Millisecond * 100) 354 defer server.Close() 355 356 //a fake server client, config is override, just used to run tests 357 cli := newTestServerClient() 358 cli.runTestRegression(c, func(config *allegrosql.Config) { 359 config.User = "root" 360 config.Net = "unix" 361 config.Addr = "/tmp/milevadbtest.sock" 362 config.DBName = "test" 363 config.Params = map[string]string{"sql_mode": "STRICT_ALL_TABLES"} 364 }, "SocketRegression") 365 366 } 367 368 // generateCert generates a private key and a certificate in PEM format based on parameters. 369 // If parentCert and parentCertKey is specified, the new certificate will be signed by the parentCert. 370 // Otherwise, the new certificate will be self-signed and is a CA. 371 func generateCert(sn int, commonName string, parentCert *x509.Certificate, parentCertKey *rsa.PrivateKey, outKeyFile string, outCertFile string, opts ...func(c *x509.Certificate)) (*x509.Certificate, *rsa.PrivateKey, error) { 372 privateKey, err := rsa.GenerateKey(rand.Reader, 528) 373 if err != nil { 374 return nil, nil, errors.Trace(err) 375 } 376 notBefore := time.Now().Add(-10 * time.Minute).UTC() 377 notAfter := notBefore.Add(1 * time.Hour).UTC() 378 379 template := x509.Certificate{ 380 SerialNumber: big.NewInt(int64(sn)), 381 Subject: pkix.Name{CommonName: commonName, Names: []pkix.AttributeTypeAndValue{soliton.MockPkixAttribute(soliton.CommonName, commonName)}}, 382 DNSNames: []string{commonName}, 383 NotBefore: notBefore, 384 NotAfter: notAfter, 385 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 386 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, 387 BasicConstraintsValid: true, 388 } 389 for _, opt := range opts { 390 opt(&template) 391 } 392 393 var parent *x509.Certificate 394 var priv *rsa.PrivateKey 395 396 if parentCert == nil || parentCertKey == nil { 397 template.IsCA = true 398 template.KeyUsage |= x509.KeyUsageCertSign 399 parent = &template 400 priv = privateKey 401 } else { 402 parent = parentCert 403 priv = parentCertKey 404 } 405 406 derBytes, err := x509.CreateCertificate(rand.Reader, &template, parent, &privateKey.PublicKey, priv) 407 if err != nil { 408 return nil, nil, errors.Trace(err) 409 } 410 411 cert, err := x509.ParseCertificate(derBytes) 412 if err != nil { 413 return nil, nil, errors.Trace(err) 414 } 415 416 certOut, err := os.Create(outCertFile) 417 if err != nil { 418 return nil, nil, errors.Trace(err) 419 } 420 pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 421 certOut.Close() 422 423 keyOut, err := os.OpenFile(outKeyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 424 if err != nil { 425 return nil, nil, errors.Trace(err) 426 } 427 pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}) 428 keyOut.Close() 429 430 return cert, privateKey, nil 431 } 432 433 // registerTLSConfig registers a allegrosql client TLS config. 434 // See https://godoc.org/github.com/go-allegrosql-driver/allegrosql#RegisterTLSConfig for details. 435 func registerTLSConfig(configName string, caCertPath string, clientCertPath string, clientKeyPath string, serverName string, verifyServer bool) error { 436 rootCertPool := x509.NewCertPool() 437 data, err := ioutil.ReadFile(caCertPath) 438 if err != nil { 439 return err 440 } 441 if ok := rootCertPool.AppendCertsFromPEM(data); !ok { 442 return errors.New("Failed to append PEM") 443 } 444 clientCert := make([]tls.Certificate, 0, 1) 445 certs, err := tls.LoadX509KeyPair(clientCertPath, clientKeyPath) 446 if err != nil { 447 return err 448 } 449 clientCert = append(clientCert, certs) 450 tlsConfig := &tls.Config{ 451 RootCAs: rootCertPool, 452 Certificates: clientCert, 453 ServerName: serverName, 454 InsecureSkipVerify: !verifyServer, 455 } 456 allegrosql.RegisterTLSConfig(configName, tlsConfig) 457 return nil 458 } 459 460 func (ts *milevadbTestSuite) TestSystemTimeZone(c *C) { 461 tk := testkit.NewTestKit(c, ts.causetstore) 462 cfg := newTestConfig() 463 cfg.Port, cfg.Status.StatusPort = 0, 0 464 cfg.Status.ReportStatus = false 465 server, err := NewServer(cfg, ts.milevadbdrv) 466 c.Assert(err, IsNil) 467 defer server.Close() 468 469 tz1 := tk.MustQuery("select variable_value from allegrosql.milevadb where variable_name = 'system_tz'").Rows() 470 tk.MustQuery("select @@system_time_zone").Check(tz1) 471 } 472 473 func (ts *milevadbTestSerialSuite) TestTLS(c *C) { 474 // Generate valid TLS certificates. 475 caCert, caKey, err := generateCert(0, "MilevaDB CA", nil, nil, "/tmp/ca-key.pem", "/tmp/ca-cert.pem") 476 c.Assert(err, IsNil) 477 _, _, err = generateCert(1, "milevadb-server", caCert, caKey, "/tmp/server-key.pem", "/tmp/server-cert.pem") 478 c.Assert(err, IsNil) 479 _, _, err = generateCert(2, "ALLEGROALLEGROSQL Client Certificate", caCert, caKey, "/tmp/client-key.pem", "/tmp/client-cert.pem") 480 c.Assert(err, IsNil) 481 err = registerTLSConfig("client-certificate", "/tmp/ca-cert.pem", "/tmp/client-cert.pem", "/tmp/client-key.pem", "milevadb-server", true) 482 c.Assert(err, IsNil) 483 484 defer func() { 485 os.Remove("/tmp/ca-key.pem") 486 os.Remove("/tmp/ca-cert.pem") 487 os.Remove("/tmp/server-key.pem") 488 os.Remove("/tmp/server-cert.pem") 489 os.Remove("/tmp/client-key.pem") 490 os.Remove("/tmp/client-cert.pem") 491 }() 492 493 // Start the server without TLS. 494 connOverrider := func(config *allegrosql.Config) { 495 config.TLSConfig = "skip-verify" 496 } 497 cli := newTestServerClient() 498 cfg := newTestConfig() 499 cfg.Port = cli.port 500 cfg.Status.ReportStatus = false 501 server, err := NewServer(cfg, ts.milevadbdrv) 502 c.Assert(err, IsNil) 503 cli.port = getPortFromTCPAddr(server.listener.Addr()) 504 go server.Run() 505 time.Sleep(time.Millisecond * 100) 506 err = cli.runTestTLSConnection(c, connOverrider) // We should get ErrNoTLS. 507 c.Assert(err, NotNil) 508 c.Assert(errors.Cause(err).Error(), Equals, allegrosql.ErrNoTLS.Error()) 509 server.Close() 510 511 // Start the server with TLS but without CA, in this case the server will not verify client's certificate. 512 connOverrider = func(config *allegrosql.Config) { 513 config.TLSConfig = "skip-verify" 514 } 515 cli = newTestServerClient() 516 cfg = newTestConfig() 517 cfg.Port = cli.port 518 cfg.Status.ReportStatus = false 519 cfg.Security = config.Security{ 520 SSLCert: "/tmp/server-cert.pem", 521 SSLKey: "/tmp/server-key.pem", 522 } 523 server, err = NewServer(cfg, ts.milevadbdrv) 524 c.Assert(err, IsNil) 525 cli.port = getPortFromTCPAddr(server.listener.Addr()) 526 go server.Run() 527 time.Sleep(time.Millisecond * 100) 528 err = cli.runTestTLSConnection(c, connOverrider) // We should establish connection successfully. 529 c.Assert(err, IsNil) 530 cli.runTestRegression(c, connOverrider, "TLSRegression") 531 // Perform server verification. 532 connOverrider = func(config *allegrosql.Config) { 533 config.TLSConfig = "client-certificate" 534 } 535 err = cli.runTestTLSConnection(c, connOverrider) // We should establish connection successfully. 536 c.Assert(err, IsNil, Commentf("%v", errors.ErrorStack(err))) 537 cli.runTestRegression(c, connOverrider, "TLSRegression") 538 server.Close() 539 540 // Start the server with TLS & CA, if the client presents its certificate, the certificate will be verified. 541 cli = newTestServerClient() 542 cfg = newTestConfig() 543 cfg.Port = cli.port 544 cfg.Status.ReportStatus = false 545 cfg.Security = config.Security{ 546 SSLCA: "/tmp/ca-cert.pem", 547 SSLCert: "/tmp/server-cert.pem", 548 SSLKey: "/tmp/server-key.pem", 549 } 550 server, err = NewServer(cfg, ts.milevadbdrv) 551 c.Assert(err, IsNil) 552 cli.port = getPortFromTCPAddr(server.listener.Addr()) 553 go server.Run() 554 time.Sleep(time.Millisecond * 100) 555 // The client does not provide a certificate, the connection should succeed. 556 err = cli.runTestTLSConnection(c, nil) 557 c.Assert(err, IsNil) 558 cli.runTestRegression(c, connOverrider, "TLSRegression") 559 // The client provides a valid certificate. 560 connOverrider = func(config *allegrosql.Config) { 561 config.TLSConfig = "client-certificate" 562 } 563 err = cli.runTestTLSConnection(c, connOverrider) 564 c.Assert(err, IsNil) 565 cli.runTestRegression(c, connOverrider, "TLSRegression") 566 server.Close() 567 568 c.Assert(soliton.IsTLSExpiredError(errors.New("unknown test")), IsFalse) 569 c.Assert(soliton.IsTLSExpiredError(x509.CertificateInvalidError{Reason: x509.CANotAuthorizedForThisName}), IsFalse) 570 c.Assert(soliton.IsTLSExpiredError(x509.CertificateInvalidError{Reason: x509.Expired}), IsTrue) 571 572 _, err = soliton.LoadTLSCertificates("", "wrong key", "wrong cert") 573 c.Assert(err, NotNil) 574 _, err = soliton.LoadTLSCertificates("wrong ca", "/tmp/server-key.pem", "/tmp/server-cert.pem") 575 c.Assert(err, NotNil) 576 } 577 578 func (ts *milevadbTestSerialSuite) TestReloadTLS(c *C) { 579 // Generate valid TLS certificates. 580 caCert, caKey, err := generateCert(0, "MilevaDB CA", nil, nil, "/tmp/ca-key-reload.pem", "/tmp/ca-cert-reload.pem") 581 c.Assert(err, IsNil) 582 _, _, err = generateCert(1, "milevadb-server", caCert, caKey, "/tmp/server-key-reload.pem", "/tmp/server-cert-reload.pem") 583 c.Assert(err, IsNil) 584 _, _, err = generateCert(2, "ALLEGROALLEGROSQL Client Certificate", caCert, caKey, "/tmp/client-key-reload.pem", "/tmp/client-cert-reload.pem") 585 c.Assert(err, IsNil) 586 err = registerTLSConfig("client-certificate-reload", "/tmp/ca-cert-reload.pem", "/tmp/client-cert-reload.pem", "/tmp/client-key-reload.pem", "milevadb-server", true) 587 c.Assert(err, IsNil) 588 589 defer func() { 590 os.Remove("/tmp/ca-key-reload.pem") 591 os.Remove("/tmp/ca-cert-reload.pem") 592 593 os.Remove("/tmp/server-key-reload.pem") 594 os.Remove("/tmp/server-cert-reload.pem") 595 os.Remove("/tmp/client-key-reload.pem") 596 os.Remove("/tmp/client-cert-reload.pem") 597 }() 598 599 // try old cert used in startup configuration. 600 cli := newTestServerClient() 601 cfg := newTestConfig() 602 cfg.Port = cli.port 603 cfg.Status.ReportStatus = false 604 cfg.Security = config.Security{ 605 SSLCA: "/tmp/ca-cert-reload.pem", 606 SSLCert: "/tmp/server-cert-reload.pem", 607 SSLKey: "/tmp/server-key-reload.pem", 608 } 609 server, err := NewServer(cfg, ts.milevadbdrv) 610 c.Assert(err, IsNil) 611 cli.port = getPortFromTCPAddr(server.listener.Addr()) 612 go server.Run() 613 time.Sleep(time.Millisecond * 100) 614 // The client provides a valid certificate. 615 connOverrider := func(config *allegrosql.Config) { 616 config.TLSConfig = "client-certificate-reload" 617 } 618 err = cli.runTestTLSConnection(c, connOverrider) 619 c.Assert(err, IsNil) 620 621 // try reload a valid cert. 622 tlsCfg := server.getTLSConfig() 623 cert, err := x509.ParseCertificate(tlsCfg.Certificates[0].Certificate[0]) 624 c.Assert(err, IsNil) 625 oldExpireTime := cert.NotAfter 626 _, _, err = generateCert(1, "milevadb-server", caCert, caKey, "/tmp/server-key-reload2.pem", "/tmp/server-cert-reload2.pem", func(c *x509.Certificate) { 627 c.NotBefore = time.Now().Add(-24 * time.Hour).UTC() 628 c.NotAfter = time.Now().Add(1 * time.Hour).UTC() 629 }) 630 c.Assert(err, IsNil) 631 os.Rename("/tmp/server-key-reload2.pem", "/tmp/server-key-reload.pem") 632 os.Rename("/tmp/server-cert-reload2.pem", "/tmp/server-cert-reload.pem") 633 connOverrider = func(config *allegrosql.Config) { 634 config.TLSConfig = "skip-verify" 635 } 636 err = cli.runReloadTLS(c, connOverrider, false) 637 c.Assert(err, IsNil) 638 connOverrider = func(config *allegrosql.Config) { 639 config.TLSConfig = "client-certificate-reload" 640 } 641 err = cli.runTestTLSConnection(c, connOverrider) 642 c.Assert(err, IsNil) 643 644 tlsCfg = server.getTLSConfig() 645 cert, err = x509.ParseCertificate(tlsCfg.Certificates[0].Certificate[0]) 646 c.Assert(err, IsNil) 647 newExpireTime := cert.NotAfter 648 c.Assert(newExpireTime.After(oldExpireTime), IsTrue) 649 650 // try reload a expired cert. 651 _, _, err = generateCert(1, "milevadb-server", caCert, caKey, "/tmp/server-key-reload3.pem", "/tmp/server-cert-reload3.pem", func(c *x509.Certificate) { 652 c.NotBefore = time.Now().Add(-24 * time.Hour).UTC() 653 c.NotAfter = c.NotBefore.Add(1 * time.Hour).UTC() 654 }) 655 c.Assert(err, IsNil) 656 os.Rename("/tmp/server-key-reload3.pem", "/tmp/server-key-reload.pem") 657 os.Rename("/tmp/server-cert-reload3.pem", "/tmp/server-cert-reload.pem") 658 connOverrider = func(config *allegrosql.Config) { 659 config.TLSConfig = "skip-verify" 660 } 661 err = cli.runReloadTLS(c, connOverrider, false) 662 c.Assert(err, IsNil) 663 connOverrider = func(config *allegrosql.Config) { 664 config.TLSConfig = "client-certificate-reload" 665 } 666 err = cli.runTestTLSConnection(c, connOverrider) 667 c.Assert(err, NotNil) 668 c.Assert(soliton.IsTLSExpiredError(err), IsTrue, Commentf("real error is %+v", err)) 669 server.Close() 670 } 671 672 func (ts *milevadbTestSerialSuite) TestErrorNoRollback(c *C) { 673 // Generate valid TLS certificates. 674 caCert, caKey, err := generateCert(0, "MilevaDB CA", nil, nil, "/tmp/ca-key-rollback.pem", "/tmp/ca-cert-rollback.pem") 675 c.Assert(err, IsNil) 676 _, _, err = generateCert(1, "milevadb-server", caCert, caKey, "/tmp/server-key-rollback.pem", "/tmp/server-cert-rollback.pem") 677 c.Assert(err, IsNil) 678 _, _, err = generateCert(2, "ALLEGROALLEGROSQL Client Certificate", caCert, caKey, "/tmp/client-key-rollback.pem", "/tmp/client-cert-rollback.pem") 679 c.Assert(err, IsNil) 680 err = registerTLSConfig("client-cert-rollback-test", "/tmp/ca-cert-rollback.pem", "/tmp/client-cert-rollback.pem", "/tmp/client-key-rollback.pem", "milevadb-server", true) 681 c.Assert(err, IsNil) 682 683 defer func() { 684 os.Remove("/tmp/ca-key-rollback.pem") 685 os.Remove("/tmp/ca-cert-rollback.pem") 686 687 os.Remove("/tmp/server-key-rollback.pem") 688 os.Remove("/tmp/server-cert-rollback.pem") 689 os.Remove("/tmp/client-key-rollback.pem") 690 os.Remove("/tmp/client-cert-rollback.pem") 691 }() 692 693 cli := newTestServerClient() 694 cfg := newTestConfig() 695 cfg.Port = cli.port 696 cfg.Status.ReportStatus = false 697 698 cfg.Security = config.Security{ 699 RequireSecureTransport: true, 700 SSLCA: "wrong path", 701 SSLCert: "wrong path", 702 SSLKey: "wrong path", 703 } 704 _, err = NewServer(cfg, ts.milevadbdrv) 705 c.Assert(err, NotNil) 706 707 // test reload tls fail with/without "error no rollback option" 708 cfg.Security = config.Security{ 709 SSLCA: "/tmp/ca-cert-rollback.pem", 710 SSLCert: "/tmp/server-cert-rollback.pem", 711 SSLKey: "/tmp/server-key-rollback.pem", 712 } 713 server, err := NewServer(cfg, ts.milevadbdrv) 714 c.Assert(err, IsNil) 715 cli.port = getPortFromTCPAddr(server.listener.Addr()) 716 go server.Run() 717 time.Sleep(time.Millisecond * 100) 718 connOverrider := func(config *allegrosql.Config) { 719 config.TLSConfig = "client-cert-rollback-test" 720 } 721 err = cli.runTestTLSConnection(c, connOverrider) 722 c.Assert(err, IsNil) 723 os.Remove("/tmp/server-key-rollback.pem") 724 err = cli.runReloadTLS(c, connOverrider, false) 725 c.Assert(err, NotNil) 726 tlsCfg := server.getTLSConfig() 727 c.Assert(tlsCfg, NotNil) 728 err = cli.runReloadTLS(c, connOverrider, true) 729 c.Assert(err, IsNil) 730 tlsCfg = server.getTLSConfig() 731 c.Assert(tlsCfg, IsNil) 732 } 733 734 func (ts *milevadbTestSuite) TestClientWithDefCauslation(c *C) { 735 c.Parallel() 736 ts.runTestClientWithDefCauslation(c) 737 } 738 739 func (ts *milevadbTestSuite) TestCreateBlockFlen(c *C) { 740 // issue #4540 741 qctx, err := ts.milevadbdrv.OpenCtx(uint64(0), 0, uint8(tmysql.DefaultDefCauslationID), "test", nil) 742 c.Assert(err, IsNil) 743 _, err = InterDircute(context.Background(), qctx, "use test;") 744 c.Assert(err, IsNil) 745 746 ctx := context.Background() 747 testALLEGROSQL := "CREATE TABLE `t1` (" + 748 "`a` char(36) NOT NULL," + 749 "`b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," + 750 "`c` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," + 751 "`d` varchar(50) DEFAULT ''," + 752 "`e` char(36) NOT NULL DEFAULT ''," + 753 "`f` char(36) NOT NULL DEFAULT ''," + 754 "`g` char(1) NOT NULL DEFAULT 'N'," + 755 "`h` varchar(100) NOT NULL," + 756 "`i` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," + 757 "`j` varchar(10) DEFAULT ''," + 758 "`k` varchar(10) DEFAULT ''," + 759 "`l` varchar(20) DEFAULT ''," + 760 "`m` varchar(20) DEFAULT ''," + 761 "`n` varchar(30) DEFAULT ''," + 762 "`o` varchar(100) DEFAULT ''," + 763 "`p` varchar(50) DEFAULT ''," + 764 "`q` varchar(50) DEFAULT ''," + 765 "`r` varchar(100) DEFAULT ''," + 766 "`s` varchar(20) DEFAULT ''," + 767 "`t` varchar(50) DEFAULT ''," + 768 "`u` varchar(100) DEFAULT ''," + 769 "`v` varchar(50) DEFAULT ''," + 770 "`w` varchar(300) NOT NULL," + 771 "`x` varchar(250) DEFAULT ''," + 772 "`y` decimal(20)," + 773 "`z` decimal(20, 4)," + 774 "PRIMARY KEY (`a`)" + 775 ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin" 776 _, err = InterDircute(ctx, qctx, testALLEGROSQL) 777 c.Assert(err, IsNil) 778 rs, err := InterDircute(ctx, qctx, "show create causet t1") 779 c.Assert(err, IsNil) 780 req := rs.NewChunk() 781 err = rs.Next(ctx, req) 782 c.Assert(err, IsNil) 783 defcaus := rs.DeferredCausets() 784 c.Assert(err, IsNil) 785 c.Assert(len(defcaus), Equals, 2) 786 c.Assert(int(defcaus[0].DeferredCausetLength), Equals, 5*tmysql.MaxBytesOfCharacter) 787 c.Assert(int(defcaus[1].DeferredCausetLength), Equals, len(req.GetRow(0).GetString(1))*tmysql.MaxBytesOfCharacter) 788 789 // for issue#5246 790 rs, err = InterDircute(ctx, qctx, "select y, z from t1") 791 c.Assert(err, IsNil) 792 defcaus = rs.DeferredCausets() 793 c.Assert(len(defcaus), Equals, 2) 794 c.Assert(int(defcaus[0].DeferredCausetLength), Equals, 21) 795 c.Assert(int(defcaus[1].DeferredCausetLength), Equals, 22) 796 } 797 798 func InterDircute(ctx context.Context, qc *MilevaDBContext, allegrosql string) (ResultSet, error) { 799 stmts, err := qc.Parse(ctx, allegrosql) 800 if err != nil { 801 return nil, err 802 } 803 if len(stmts) != 1 { 804 panic("wrong input for InterDircute: " + allegrosql) 805 } 806 return qc.InterDircuteStmt(ctx, stmts[0]) 807 } 808 809 func (ts *milevadbTestSuite) TestShowBlocksFlen(c *C) { 810 qctx, err := ts.milevadbdrv.OpenCtx(uint64(0), 0, uint8(tmysql.DefaultDefCauslationID), "test", nil) 811 c.Assert(err, IsNil) 812 ctx := context.Background() 813 _, err = InterDircute(ctx, qctx, "use test;") 814 c.Assert(err, IsNil) 815 816 testALLEGROSQL := "create causet abcdefghijklmnopqrstuvwxyz (i int)" 817 _, err = InterDircute(ctx, qctx, testALLEGROSQL) 818 c.Assert(err, IsNil) 819 rs, err := InterDircute(ctx, qctx, "show blocks") 820 c.Assert(err, IsNil) 821 req := rs.NewChunk() 822 err = rs.Next(ctx, req) 823 c.Assert(err, IsNil) 824 defcaus := rs.DeferredCausets() 825 c.Assert(err, IsNil) 826 c.Assert(len(defcaus), Equals, 1) 827 c.Assert(int(defcaus[0].DeferredCausetLength), Equals, 26*tmysql.MaxBytesOfCharacter) 828 } 829 830 func checkDefCausNames(c *C, defCausumns []*DeferredCausetInfo, names ...string) { 831 for i, name := range names { 832 c.Assert(defCausumns[i].Name, Equals, name) 833 c.Assert(defCausumns[i].OrgName, Equals, name) 834 } 835 } 836 837 func (ts *milevadbTestSuite) TestFieldList(c *C) { 838 qctx, err := ts.milevadbdrv.OpenCtx(uint64(0), 0, uint8(tmysql.DefaultDefCauslationID), "test", nil) 839 c.Assert(err, IsNil) 840 _, err = InterDircute(context.Background(), qctx, "use test;") 841 c.Assert(err, IsNil) 842 843 ctx := context.Background() 844 testALLEGROSQL := `create causet t ( 845 c_bit bit(10), 846 c_int_d int, 847 c_bigint_d bigint, 848 c_float_d float, 849 c_double_d double, 850 c_decimal decimal(6, 3), 851 c_datetime datetime(2), 852 c_time time(3), 853 c_date date, 854 c_timestamp timestamp(4) DEFAULT CURRENT_TIMESTAMP(4), 855 c_char char(20), 856 c_varchar varchar(20), 857 c_text_d text, 858 c_binary binary(20), 859 c_blob_d blob, 860 c_set set('a', 'b', 'c'), 861 c_enum enum('a', 'b', 'c'), 862 c_json JSON, 863 c_year year 864 )` 865 _, err = InterDircute(ctx, qctx, testALLEGROSQL) 866 c.Assert(err, IsNil) 867 defCausInfos, err := qctx.FieldList("t") 868 c.Assert(err, IsNil) 869 c.Assert(len(defCausInfos), Equals, 19) 870 871 checkDefCausNames(c, defCausInfos, "c_bit", "c_int_d", "c_bigint_d", "c_float_d", 872 "c_double_d", "c_decimal", "c_datetime", "c_time", "c_date", "c_timestamp", 873 "c_char", "c_varchar", "c_text_d", "c_binary", "c_blob_d", "c_set", "c_enum", 874 "c_json", "c_year") 875 876 for _, defcaus := range defCausInfos { 877 c.Assert(defcaus.Schema, Equals, "test") 878 } 879 880 for _, defcaus := range defCausInfos { 881 c.Assert(defcaus.Block, Equals, "t") 882 } 883 884 for i, defCaus := range defCausInfos { 885 switch i { 886 case 10, 11, 12, 15, 16: 887 // c_char char(20), c_varchar varchar(20), c_text_d text, 888 // c_set set('a', 'b', 'c'), c_enum enum('a', 'b', 'c') 889 c.Assert(defCaus.Charset, Equals, uint16(tmysql.CharsetNameToID(tmysql.DefaultCharset)), Commentf("index %d", i)) 890 continue 891 } 892 893 c.Assert(defCaus.Charset, Equals, uint16(tmysql.CharsetNameToID("binary")), Commentf("index %d", i)) 894 } 895 896 // c_decimal decimal(6, 3) 897 c.Assert(defCausInfos[5].Decimal, Equals, uint8(3)) 898 899 // for issue#10513 900 tooLongDeferredCausetAsName := "COALESCE(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)" 901 defCausumnAsName := tooLongDeferredCausetAsName[:tmysql.MaxAliasIdentifierLen] 902 903 rs, err := InterDircute(ctx, qctx, "select "+tooLongDeferredCausetAsName) 904 c.Assert(err, IsNil) 905 defcaus := rs.DeferredCausets() 906 c.Assert(defcaus[0].OrgName, Equals, tooLongDeferredCausetAsName) 907 c.Assert(defcaus[0].Name, Equals, defCausumnAsName) 908 909 rs, err = InterDircute(ctx, qctx, "select c_bit as '"+tooLongDeferredCausetAsName+"' from t") 910 c.Assert(err, IsNil) 911 defcaus = rs.DeferredCausets() 912 c.Assert(defcaus[0].OrgName, Equals, "c_bit") 913 c.Assert(defcaus[0].Name, Equals, defCausumnAsName) 914 } 915 916 func (ts *milevadbTestSuite) TestSumAvg(c *C) { 917 c.Parallel() 918 ts.runTestSumAvg(c) 919 } 920 921 func (ts *milevadbTestSuite) TestNullFlag(c *C) { 922 // issue #9689 923 qctx, err := ts.milevadbdrv.OpenCtx(uint64(0), 0, uint8(tmysql.DefaultDefCauslationID), "test", nil) 924 c.Assert(err, IsNil) 925 926 ctx := context.Background() 927 rs, err := InterDircute(ctx, qctx, "select 1") 928 c.Assert(err, IsNil) 929 defcaus := rs.DeferredCausets() 930 c.Assert(len(defcaus), Equals, 1) 931 expectFlag := uint16(tmysql.NotNullFlag | tmysql.BinaryFlag) 932 c.Assert(dumpFlag(defcaus[0].Type, defcaus[0].Flag), Equals, expectFlag) 933 }