github.com/dolthub/go-mysql-server@v0.18.0/enginetest/queries/priv_auth_queries.go (about) 1 // Copyright 2022 Dolthub, 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package queries 16 17 import ( 18 "testing" 19 "time" 20 21 "gopkg.in/src-d/go-errors.v1" 22 23 sqle "github.com/dolthub/go-mysql-server" 24 "github.com/dolthub/go-mysql-server/sql" 25 "github.com/dolthub/go-mysql-server/sql/mysql_db" 26 "github.com/dolthub/go-mysql-server/sql/plan" 27 "github.com/dolthub/go-mysql-server/sql/types" 28 ) 29 30 // UserPrivilegeTest is used to define a test on the user and privilege systems. These tests always have the root 31 // account available, and the root account is used with any queries in the SetUpScript. 32 type UserPrivilegeTest struct { 33 Name string 34 SetUpScript []string 35 Assertions []UserPrivilegeTestAssertion 36 } 37 38 // UserPrivilegeTestAssertion is within a UserPrivilegeTest to assert functionality. 39 type UserPrivilegeTestAssertion struct { 40 User string 41 Host string 42 Query string 43 Expected []sql.Row 44 ExpectedErr *errors.Kind 45 ExpectedErrStr string 46 } 47 48 // QuickPrivilegeTest specifically tests privileges on a predefined user (tester@localhost) using predefined tables and 49 // databases. Every test here can easily be represented by a UserPrivilegeTest, however this is intended to test 50 // specific privileges at a large scale, meaning there may be thousands of these tests, and hence the test data should 51 // be as small as possible. 52 // 53 // All queries will be run as a root user with full privileges (intended for setup), with the last query running as the 54 // testing user (tester@localhost). For example, the first query may grant a SELECT privilege, while the second query 55 // is the SELECT query. Of note, the current database as set by the context is retained when switching from the root 56 // user to the test user. This does not mean that the test user automatically gains access to the database, but this is 57 // used for any queries that (incorrectly) only work with the current database. 58 // 59 // ExpectingErr should be set when an error is expected, and it does not matter what the error is so long that it is one 60 // of the errors related to privilege checking (meaning a failed INSERT due to a missing column is NOT caught). If 61 // ExpectingErr is set and an error is given to ExpectedErr, then it is enforced that the error matches. However, if 62 // ExpectingErr is set and ExpectedErr is nil, then any privilege checking error will match. 63 // 64 // Expected makes a distinction between the nil value and the empty value. A nil value means that we do not care about 65 // the result, only that it did not error (unless one of the error-asserting fields are set). A non-nil value asserts 66 // that the returned value matches our Expected value. If the returned value is nil, then we make a special case to 67 // match the non-nil empty row with it, due to the aforementioned distinction. 68 // 69 // Statements that are run before every test (the state that all tests start with): 70 // CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY, v1 BIGINT); 71 // CREATE TABLE mydb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT); 72 // CREATE TABLE otherdb.test (pk BIGINT PRIMARY KEY, v1 BIGINT); 73 // CREATE TABLE otherdb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT); 74 // INSERT INTO mydb.test VALUES (0, 0), (1, 1); 75 // INSERT INTO mydb.test2 VALUES (0, 1), (1, 2); 76 // INSERT INTO otherdb.test VALUES (1, 1), (2, 2); 77 // INSERT INTO otherdb.test2 VALUES (1, 1), (2, 2); 78 type QuickPrivilegeTest struct { 79 Queries []string 80 Expected []sql.Row 81 ExpectedErr *errors.Kind 82 ExpectingErr bool 83 } 84 85 // ServerAuthenticationTest is used to define a test on the server authentication system. These tests always have the 86 // root account available, and the root account is used with any queries in the SetUpScript. The SetUpFunc is run before 87 // the SetUpScript. 88 type ServerAuthenticationTest struct { 89 Name string 90 SetUpFunc func(ctx *sql.Context, t *testing.T, engine *sqle.Engine) 91 SetUpScript []string 92 Assertions []ServerAuthenticationTestAssertion 93 } 94 95 // ServerAuthenticationTestAssertion is within a ServerAuthenticationTest to assert functionality. 96 type ServerAuthenticationTestAssertion struct { 97 Username string 98 Password string 99 Query string 100 ExpectedErr bool 101 ExpectedErrKind *errors.Kind 102 ExpectedErrStr string 103 } 104 105 // UserPrivTests test the user and privilege systems. These tests always have the root account available, and the root 106 // account is used with any queries in the SetUpScript. 107 var UserPrivTests = []UserPrivilegeTest{ 108 { 109 Name: "Binlog replication privileges", 110 SetUpScript: []string{ 111 "CREATE USER user@localhost;", 112 "CREATE USER 'replica-admin'@localhost;", 113 "CREATE USER 'replica-client'@localhost;", 114 "CREATE USER 'replica-reload'@localhost;", 115 // REPLICATION_SLAVE_ADMIN allows: start replica, 116 "GRANT REPLICATION_SLAVE_ADMIN ON *.* TO 'replica-admin'@localhost;", 117 // REPLICATION CLIENT allows: show replica status 118 "GRANT REPLICATION CLIENT ON *.* to 'replica-client'@localhost;", 119 // RELOAD allows: reset replica 120 "GRANT RELOAD ON *.* TO 'replica-reload'@localhost;", 121 }, 122 Assertions: []UserPrivilegeTestAssertion{ 123 // START REPLICA 124 { 125 User: "user", 126 Host: "localhost", 127 Query: "START REPLICA", 128 ExpectedErr: sql.ErrPrivilegeCheckFailed, 129 }, 130 { 131 // ErrNoReplicationController means the priv check passed 132 User: "replica-admin", 133 Host: "localhost", 134 Query: "START REPLICA", 135 ExpectedErr: plan.ErrNoReplicationController, 136 }, 137 { 138 User: "replica-client", 139 Host: "localhost", 140 Query: "START REPLICA", 141 ExpectedErr: sql.ErrPrivilegeCheckFailed, 142 }, 143 { 144 User: "replica-reload", 145 Host: "localhost", 146 Query: "START REPLICA", 147 ExpectedErr: sql.ErrPrivilegeCheckFailed, 148 }, 149 { 150 User: "root", 151 Host: "localhost", 152 Query: "START REPLICA", 153 ExpectedErr: plan.ErrNoReplicationController, 154 }, 155 156 // STOP REPLICA 157 { 158 User: "user", 159 Host: "localhost", 160 Query: "STOP REPLICA", 161 ExpectedErr: sql.ErrPrivilegeCheckFailed, 162 }, 163 { 164 // ErrNoReplicationController means the priv check passed 165 User: "replica-admin", 166 Host: "localhost", 167 Query: "STOP REPLICA", 168 ExpectedErr: plan.ErrNoReplicationController, 169 }, 170 { 171 User: "replica-client", 172 Host: "localhost", 173 Query: "STOP REPLICA", 174 ExpectedErr: sql.ErrPrivilegeCheckFailed, 175 }, 176 { 177 User: "replica-reload", 178 Host: "localhost", 179 Query: "STOP REPLICA", 180 ExpectedErr: sql.ErrPrivilegeCheckFailed, 181 }, 182 { 183 User: "root", 184 Host: "localhost", 185 Query: "STOP REPLICA", 186 ExpectedErr: plan.ErrNoReplicationController, 187 }, 188 189 // RESET REPLICA 190 { 191 User: "user", 192 Host: "localhost", 193 Query: "RESET REPLICA", 194 ExpectedErr: sql.ErrPrivilegeCheckFailed, 195 }, 196 { 197 User: "replica-admin", 198 Host: "localhost", 199 Query: "RESET REPLICA", 200 ExpectedErr: sql.ErrPrivilegeCheckFailed, 201 }, 202 { 203 User: "replica-client", 204 Host: "localhost", 205 Query: "RESET REPLICA", 206 ExpectedErr: sql.ErrPrivilegeCheckFailed, 207 }, 208 { 209 // ErrNoReplicationController means the priv check passed 210 User: "replica-reload", 211 Host: "localhost", 212 Query: "RESET REPLICA", 213 ExpectedErr: plan.ErrNoReplicationController, 214 }, 215 { 216 User: "root", 217 Host: "localhost", 218 Query: "RESET REPLICA", 219 ExpectedErr: plan.ErrNoReplicationController, 220 }, 221 222 // SHOW REPLICA STATUS 223 { 224 User: "user", 225 Host: "localhost", 226 Query: "SHOW REPLICA STATUS;", 227 ExpectedErr: sql.ErrPrivilegeCheckFailed, 228 }, 229 { 230 User: "replica-admin", 231 Host: "localhost", 232 Query: "SHOW REPLICA STATUS;", 233 ExpectedErr: sql.ErrPrivilegeCheckFailed, 234 }, 235 { 236 User: "replica-client", 237 Host: "localhost", 238 Query: "SHOW REPLICA STATUS;", 239 Expected: []sql.Row{}, 240 }, 241 { 242 User: "replica-reload", 243 Host: "localhost", 244 Query: "SHOW REPLICA STATUS;", 245 ExpectedErr: sql.ErrPrivilegeCheckFailed, 246 }, 247 { 248 User: "root", 249 Host: "localhost", 250 Query: "SHOW REPLICA STATUS;", 251 Expected: []sql.Row{}, 252 }, 253 254 // CHANGE REPLICATION SOURCE 255 { 256 User: "user", 257 Host: "localhost", 258 Query: "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';", 259 ExpectedErr: sql.ErrPrivilegeCheckFailed, 260 }, 261 { 262 // ErrNoReplicationController means the priv check passed 263 User: "replica-admin", 264 Host: "localhost", 265 Query: "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';", 266 ExpectedErr: plan.ErrNoReplicationController, 267 }, 268 { 269 User: "replica-client", 270 Host: "localhost", 271 Query: "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';", 272 ExpectedErr: sql.ErrPrivilegeCheckFailed, 273 }, 274 { 275 User: "replica-reload", 276 Host: "localhost", 277 Query: "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';", 278 ExpectedErr: sql.ErrPrivilegeCheckFailed, 279 }, 280 { 281 User: "root", 282 Host: "localhost", 283 Query: "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';", 284 ExpectedErr: plan.ErrNoReplicationController, 285 }, 286 287 // CHANGE REPLICATION FILTER 288 { 289 User: "user", 290 Host: "localhost", 291 Query: "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);", 292 ExpectedErr: sql.ErrPrivilegeCheckFailed, 293 }, 294 { 295 // ErrNoReplicationController means the priv check passed 296 User: "replica-admin", 297 Host: "localhost", 298 Query: "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);", 299 ExpectedErr: plan.ErrNoReplicationController, 300 }, 301 { 302 User: "replica-client", 303 Host: "localhost", 304 Query: "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);", 305 ExpectedErr: sql.ErrPrivilegeCheckFailed, 306 }, 307 { 308 User: "replica-reload", 309 Host: "localhost", 310 Query: "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);", 311 ExpectedErr: sql.ErrPrivilegeCheckFailed, 312 }, 313 { 314 User: "root", 315 Host: "localhost", 316 Query: "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);", 317 ExpectedErr: plan.ErrNoReplicationController, 318 }, 319 }, 320 }, 321 { 322 Name: "Basic database and table name visibility", 323 SetUpScript: []string{ 324 "CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY);", 325 "INSERT INTO mydb.test VALUES (1);", 326 "CREATE USER tester@localhost;", 327 "CREATE ROLE test_role;", 328 "GRANT SELECT ON mydb.* TO test_role;", 329 }, 330 Assertions: []UserPrivilegeTestAssertion{ 331 { 332 User: "tester", 333 Host: "localhost", 334 Query: "SELECT * FROM mydb.test;/*1*/", 335 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 336 }, 337 { 338 User: "tester", 339 Host: "localhost", 340 Query: "SELECT * FROM mydb.test2;/*1*/", 341 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 342 }, 343 { 344 User: "root", 345 Host: "localhost", 346 Query: "GRANT SELECT ON *.* TO tester@localhost;", 347 Expected: []sql.Row{{types.NewOkResult(0)}}, 348 }, 349 { 350 User: "tester", 351 Host: "localhost", 352 Query: "SELECT * FROM mydb.test;/*2*/", 353 Expected: []sql.Row{{1}}, 354 }, 355 { 356 User: "tester", 357 Host: "localhost", 358 Query: "SELECT * FROM mydb.test2;/*2*/", 359 ExpectedErr: sql.ErrTableNotFound, 360 }, 361 { 362 User: "root", 363 Host: "localhost", 364 Query: "REVOKE SELECT ON *.* FROM tester@localhost;", 365 Expected: []sql.Row{{types.NewOkResult(0)}}, 366 }, 367 { // Ensure we've reverted to initial state (all SELECTs after REVOKEs are doing this) 368 User: "tester", 369 Host: "localhost", 370 Query: "SELECT * FROM mydb.test;/*3*/", 371 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 372 }, 373 { 374 User: "tester", 375 Host: "localhost", 376 Query: "SELECT * FROM mydb.test2;/*3*/", 377 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 378 }, 379 { 380 User: "root", 381 Host: "localhost", 382 Query: "GRANT SELECT ON mydb.* TO tester@localhost;", 383 Expected: []sql.Row{{types.NewOkResult(0)}}, 384 }, 385 { 386 User: "tester", 387 Host: "localhost", 388 Query: "SELECT * FROM mydb.test;/*4*/", 389 Expected: []sql.Row{{1}}, 390 }, 391 { 392 User: "tester", 393 Host: "localhost", 394 Query: "SELECT * FROM mydb.test2;/*4*/", 395 ExpectedErr: sql.ErrTableNotFound, 396 }, 397 { 398 User: "root", 399 Host: "localhost", 400 Query: "REVOKE SELECT ON mydb.* FROM tester@localhost;", 401 Expected: []sql.Row{{types.NewOkResult(0)}}, 402 }, 403 { 404 User: "tester", 405 Host: "localhost", 406 Query: "SELECT * FROM mydb.test;/*5*/", 407 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 408 }, 409 { 410 User: "tester", 411 Host: "localhost", 412 Query: "SELECT * FROM mydb.test2;/*5*/", 413 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 414 }, 415 { 416 User: "root", 417 Host: "localhost", 418 Query: "GRANT SELECT ON mydb.test TO tester@localhost;", 419 Expected: []sql.Row{{types.NewOkResult(0)}}, 420 }, 421 { 422 User: "tester", 423 Host: "localhost", 424 Query: "SELECT * FROM mydb.test;/*6*/", 425 Expected: []sql.Row{{1}}, 426 }, 427 { 428 User: "tester", 429 Host: "localhost", 430 Query: "SELECT * FROM mydb.test2;/*6*/", 431 ExpectedErr: sql.ErrTableAccessDeniedForUser, 432 }, 433 { 434 User: "root", 435 Host: "localhost", 436 Query: "REVOKE SELECT ON mydb.test FROM tester@localhost;", 437 Expected: []sql.Row{{types.NewOkResult(0)}}, 438 }, 439 { 440 User: "tester", 441 Host: "localhost", 442 Query: "SELECT * FROM mydb.test;/*7*/", 443 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 444 }, 445 { 446 User: "tester", 447 Host: "localhost", 448 Query: "SELECT * FROM mydb.test2;/*7*/", 449 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 450 }, 451 { 452 User: "root", 453 Host: "localhost", 454 Query: "GRANT SELECT ON mydb.test2 TO tester@localhost;", 455 Expected: []sql.Row{{types.NewOkResult(0)}}, 456 }, 457 { 458 User: "tester", 459 Host: "localhost", 460 Query: "SELECT * FROM mydb.test;/*8*/", 461 ExpectedErr: sql.ErrTableAccessDeniedForUser, 462 }, 463 { 464 User: "tester", 465 Host: "localhost", 466 Query: "SELECT * FROM mydb.test2;/*8*/", 467 ExpectedErr: sql.ErrTableNotFound, 468 }, 469 { 470 User: "root", 471 Host: "localhost", 472 Query: "REVOKE SELECT ON mydb.test2 FROM tester@localhost;", 473 Expected: []sql.Row{{types.NewOkResult(0)}}, 474 }, 475 { 476 User: "tester", 477 Host: "localhost", 478 Query: "SELECT * FROM mydb.test;/*9*/", 479 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 480 }, 481 { 482 User: "tester", 483 Host: "localhost", 484 Query: "SELECT * FROM mydb.test2;/*9*/", 485 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 486 }, 487 { 488 User: "root", 489 Host: "localhost", 490 Query: "GRANT test_role TO tester@localhost;", 491 Expected: []sql.Row{{types.NewOkResult(0)}}, 492 }, 493 { 494 User: "tester", 495 Host: "localhost", 496 Query: "SELECT * FROM mydb.test;/*10*/", 497 Expected: []sql.Row{{1}}, 498 }, 499 { 500 User: "tester", 501 Host: "localhost", 502 Query: "SELECT * FROM mydb.test2;/*10*/", 503 ExpectedErr: sql.ErrTableNotFound, 504 }, 505 }, 506 }, 507 { 508 Name: "Basic user creation", 509 SetUpScript: []string{ 510 "CREATE USER testuser@`127.0.0.1`;", 511 }, 512 Assertions: []UserPrivilegeTestAssertion{ 513 { 514 Query: "CREATE USER testuser@`127.0.0.1`;", 515 ExpectedErr: sql.ErrUserCreationFailure, 516 }, 517 { 518 Query: "CREATE USER IF NOT EXISTS testuser@`127.0.0.1`;", 519 Expected: []sql.Row{{types.NewOkResult(0)}}, 520 }, 521 { 522 Query: "INSERT INTO mysql.user (Host, User) VALUES ('localhost', 'testuser2');", 523 Expected: []sql.Row{{types.NewOkResult(1)}}, 524 }, 525 { 526 Query: "SELECT * FROM mysql.user WHERE User = 'root';", 527 Expected: []sql.Row{ 528 { 529 "localhost", // Host 530 "root", // User 531 "Y", // Select_priv 532 "Y", // Insert_priv 533 "Y", // Update_priv 534 "Y", // Delete_priv 535 "Y", // Create_priv 536 "Y", // Drop_priv 537 "Y", // Reload_priv 538 "Y", // Shutdown_priv 539 "Y", // Process_priv 540 "Y", // File_priv 541 "Y", // Grant_priv 542 "Y", // References_priv 543 "Y", // Index_priv 544 "Y", // Alter_priv 545 "Y", // Show_db_priv 546 "Y", // Super_priv 547 "Y", // Create_tmp_table_priv 548 "Y", // Lock_tables_priv 549 "Y", // Execute_priv 550 "Y", // Repl_slave_priv 551 "Y", // Repl_client_priv 552 "Y", // Create_view_priv 553 "Y", // Show_view_priv 554 "Y", // Create_routine_priv 555 "Y", // Alter_routine_priv 556 "Y", // Create_user_priv 557 "Y", // Event_priv 558 "Y", // Trigger_priv 559 "Y", // Create_tablespace_priv 560 "", // ssl_type 561 []byte(""), // ssl_cipher 562 []byte(""), // x509_issuer 563 []byte(""), // x509_subject 564 uint32(0), // max_questions 565 uint32(0), // max_updates 566 uint32(0), // max_connections 567 uint32(0), // max_user_connections 568 "mysql_native_password", // plugin 569 "", // authentication_string 570 "N", // password_expired 571 time.Unix(1, 0).UTC(), // password_last_changed 572 nil, // password_lifetime 573 "N", // account_locked 574 "Y", // Create_role_priv 575 "Y", // Drop_role_priv 576 nil, // Password_reuse_history 577 nil, // Password_reuse_time 578 nil, // Password_require_current 579 nil, // User_attributes 580 "", // identity 581 }, 582 }, 583 }, 584 { 585 Query: "SELECT Host, User FROM mysql.user;", 586 Expected: []sql.Row{ 587 {"localhost", "root"}, 588 {"localhost", "testuser2"}, 589 {"127.0.0.1", "testuser"}, 590 }, 591 }, 592 }, 593 }, 594 { 595 Name: "Dynamic privilege support", 596 SetUpScript: []string{ 597 "CREATE USER testuser@localhost;", 598 "GRANT REPLICATION_SLAVE_ADMIN ON *.* TO testuser@localhost;", 599 "GRANT CLONE_ADMIN ON *.* TO testuser@localhost;", 600 }, 601 Assertions: []UserPrivilegeTestAssertion{ 602 { 603 Query: "SELECT user, host from mysql.user", 604 Expected: []sql.Row{ 605 {"root", "localhost"}, 606 {"testuser", "localhost"}, 607 }, 608 }, 609 { 610 User: "root", 611 Host: "localhost", 612 Query: "SHOW GRANTS FOR testuser@localhost;", 613 Expected: []sql.Row{ 614 {"GRANT USAGE ON *.* TO `testuser`@`localhost`"}, 615 {"GRANT CLONE_ADMIN, REPLICATION_SLAVE_ADMIN ON *.* TO `testuser`@`localhost`"}, 616 }, 617 }, 618 { 619 // Dynamic privileges may only be applied globally 620 User: "root", 621 Host: "localhost", 622 Query: "GRANT REPLICATION_SLAVE_ADMIN ON mydb.* TO 'testuser'@'localhost';", 623 ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage, 624 }, 625 { 626 // Dynamic privileges may only be applied globally 627 User: "root", 628 Host: "localhost", 629 Query: "GRANT REPLICATION_SLAVE_ADMIN ON mydb.mytable TO 'testuser'@'localhost';", 630 ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage, 631 }, 632 { 633 // Dynamic privileges may only be applied globally 634 User: "root", 635 Host: "localhost", 636 Query: "REVOKE REPLICATION_SLAVE_ADMIN ON mydb.* FROM 'testuser'@'localhost';", 637 ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage, 638 }, 639 { 640 // Dynamic privileges may only be applied globally 641 User: "root", 642 Host: "localhost", 643 Query: "REVOKE REPLICATION_SLAVE_ADMIN ON mydb.mytable FROM 'testuser'@'localhost';", 644 ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage, 645 }, 646 }, 647 }, 648 { 649 Name: "user creation no host", 650 SetUpScript: []string{ 651 "CREATE USER testuser;", 652 }, 653 Assertions: []UserPrivilegeTestAssertion{ 654 { 655 Query: "SELECT user, host from mysql.user", 656 Expected: []sql.Row{ 657 {"root", "localhost"}, 658 {"testuser", "%"}, 659 }, 660 }, 661 }, 662 }, 663 { 664 Name: "grants at various scopes no host", 665 SetUpScript: []string{ 666 "CREATE USER tester;", 667 "GRANT SELECT ON *.* to tester", 668 "GRANT SELECT ON db.* to tester", 669 "GRANT SELECT ON db.tbl to tester", 670 }, 671 Assertions: []UserPrivilegeTestAssertion{ 672 { 673 User: "root", 674 Host: "localhost", 675 Query: "SHOW GRANTS FOR tester@localhost;", 676 Expected: []sql.Row{ 677 {"GRANT SELECT ON *.* TO `tester`@`%`"}, 678 {"GRANT SELECT ON `db`.* TO `tester`@`%`"}, 679 {"GRANT SELECT ON `db`.`tbl` TO `tester`@`%`"}, 680 }, 681 }, 682 }, 683 }, 684 { 685 Name: "procedure grants and restrictions", 686 SetUpScript: []string{ 687 "CREATE USER granted@localhost", 688 "GRANT EXECUTE ON mydb.* TO granted@localhost", 689 "GRANT EXECUTE ON PROCEDURE mydb.memory_admin_only TO granted@localhost", // Explicit grant on admin only proc 690 "CREATE USER denied@localhost", 691 "GRANT EXECUTE ON mydb.* TO denied@localhost", // Access to DB, but not to admin proc. 692 "CREATE USER targeted@localhost", 693 "GRANT EXECUTE ON PROCEDURE mydb.memory_admin_only TO targeted@localhost", // Explicit grant on admin only proc, even though no access to DB. 694 "CREATE USER noaccess@localhost", // Ensure this user can't run any procedure 695 }, 696 Assertions: []UserPrivilegeTestAssertion{ 697 { 698 User: "granted", 699 Host: "localhost", 700 Query: "CALL mydb.memory_admin_only(1,2)", 701 Expected: []sql.Row{{3}}, 702 }, 703 { 704 User: "denied", 705 Host: "localhost", 706 Query: "CALL mydb.memory_variadic_add(3,2)", // Verify this user _can_ access non-admin proc 707 Expected: []sql.Row{{5}}, 708 }, 709 { 710 User: "denied", 711 Host: "localhost", 712 Query: "CALL mydb.memory_admin_only(1,2)", 713 ExpectedErrStr: "command denied to user 'denied'@'localhost'", 714 }, 715 { 716 User: "targeted", 717 Host: "localhost", 718 Query: "CALL mydb.memory_variadic_add(3,2)", // Verify this user _can't_ access non-admin proc 719 ExpectedErrStr: "command denied to user 'targeted'@'localhost'", 720 }, 721 { 722 User: "targeted", 723 Host: "localhost", 724 Query: "CALL mydb.memory_admin_only(7,2)", 725 Expected: []sql.Row{{9}}, 726 }, 727 { 728 User: "noaccess", 729 Host: "localhost", 730 Query: "CALL mydb.memory_variadic_add(3,2)", // Verify this user can't access non-admin proc 731 ExpectedErrStr: "Access denied for user 'noaccess'@'localhost' to database 'mydb'", 732 }, 733 { 734 User: "noaccess", 735 Host: "localhost", 736 Query: "CALL mydb.memory_admin_only(1,2)", 737 ExpectedErrStr: "Access denied for user 'noaccess'@'localhost' to database 'mydb'", 738 }, 739 }, 740 }, 741 { 742 Name: "Valid users without privileges may use the dual table", 743 SetUpScript: []string{ 744 "CREATE USER tester@localhost;", 745 }, 746 Assertions: []UserPrivilegeTestAssertion{ 747 { 748 User: "tester", 749 Host: "localhost", 750 Query: "SELECT 1+2;", 751 Expected: []sql.Row{{3}}, 752 }, 753 { 754 User: "noexist", 755 Host: "localhost", 756 Query: "SELECT 1+2;", 757 ExpectedErrStr: "Access denied for user 'noexist' (errno 1045) (sqlstate 28000)", 758 }, 759 }, 760 }, 761 { 762 Name: "Basic SELECT and INSERT privilege checking", 763 SetUpScript: []string{ 764 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 765 "INSERT INTO test VALUES (1), (2), (3);", 766 "CREATE USER tester@localhost;", 767 }, 768 Assertions: []UserPrivilegeTestAssertion{ 769 { 770 User: "tester", 771 Host: "localhost", 772 Query: "INSERT INTO test VALUES (4);", 773 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 774 }, 775 { 776 User: "root", 777 Host: "localhost", 778 Query: "GRANT INSERT ON *.* TO tester@localhost;", 779 Expected: []sql.Row{{types.NewOkResult(0)}}, 780 }, 781 { 782 User: "tester", 783 Host: "localhost", 784 Query: "INSERT INTO test VALUES (4);", 785 Expected: []sql.Row{{types.NewOkResult(1)}}, 786 }, 787 { 788 User: "tester", 789 Host: "localhost", 790 Query: "SELECT * FROM test;", 791 ExpectedErr: sql.ErrPrivilegeCheckFailed, 792 }, 793 { 794 User: "root", 795 Host: "localhost", 796 Query: "SELECT * FROM test;", 797 Expected: []sql.Row{{1}, {2}, {3}, {4}}, 798 }, 799 { 800 User: "root", 801 Host: "localhost", 802 Query: "GRANT SELECT ON *.* TO tester@localhost;", 803 Expected: []sql.Row{{types.NewOkResult(0)}}, 804 }, 805 { 806 User: "tester", 807 Host: "localhost", 808 Query: "SELECT * FROM test;", 809 Expected: []sql.Row{{1}, {2}, {3}, {4}}, 810 }, 811 }, 812 }, 813 { 814 Name: "Database-level privileges exist", 815 SetUpScript: []string{ 816 "CREATE USER tester@localhost;", 817 }, 818 Assertions: []UserPrivilegeTestAssertion{ 819 { 820 User: "root", 821 Host: "localhost", 822 Query: "GRANT SELECT, UPDATE, EXECUTE ON mydb.* TO tester@localhost;", 823 Expected: []sql.Row{{types.NewOkResult(0)}}, 824 }, 825 { 826 User: "root", 827 Host: "localhost", 828 Query: "SELECT * FROM mysql.db;", 829 Expected: []sql.Row{{"localhost", "mydb", "tester", "Y", "N", "Y", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "Y", "N", "N"}}, 830 }, 831 { 832 User: "root", 833 Host: "localhost", 834 Query: "REVOKE UPDATE ON mydb.* FROM tester@localhost;", 835 Expected: []sql.Row{{types.NewOkResult(0)}}, 836 }, 837 { 838 User: "root", 839 Host: "localhost", 840 Query: "SELECT * FROM mysql.db;", 841 Expected: []sql.Row{{"localhost", "mydb", "tester", "Y", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "Y", "N", "N"}}, 842 }, 843 { 844 User: "root", 845 Host: "localhost", 846 Query: "UPDATE mysql.db SET Insert_priv = 'Y' WHERE User = 'tester';", 847 Expected: []sql.Row{{types.OkResult{ 848 RowsAffected: 1, 849 InsertID: 0, 850 Info: plan.UpdateInfo{ 851 Matched: 1, 852 Updated: 1, 853 Warnings: 0, 854 }, 855 }}}, 856 }, 857 { 858 User: "root", 859 Host: "localhost", 860 Query: "SELECT * FROM mysql.db;", 861 Expected: []sql.Row{{"localhost", "mydb", "tester", "Y", "Y", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "N", "Y", "N", "N"}}, 862 }, 863 }, 864 }, 865 { 866 Name: "Table-level privileges exist", 867 SetUpScript: []string{ 868 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 869 "CREATE USER tester@localhost;", 870 }, 871 Assertions: []UserPrivilegeTestAssertion{ 872 { 873 User: "root", 874 Host: "localhost", 875 Query: "GRANT SELECT, DELETE, DROP ON mydb.test TO tester@localhost;", 876 Expected: []sql.Row{{types.NewOkResult(0)}}, 877 }, 878 { 879 User: "root", 880 Host: "localhost", 881 Query: "SELECT * FROM mysql.tables_priv;", 882 Expected: []sql.Row{{"localhost", "mydb", "tester", "test", "", time.Unix(1, 0).UTC(), "Select,Delete,Drop", ""}}, 883 }, 884 { 885 User: "root", 886 Host: "localhost", 887 Query: "REVOKE DELETE ON mydb.test FROM tester@localhost;", 888 Expected: []sql.Row{{types.NewOkResult(0)}}, 889 }, 890 { 891 User: "root", 892 Host: "localhost", 893 Query: "SELECT * FROM mysql.tables_priv;", 894 Expected: []sql.Row{{"localhost", "mydb", "tester", "test", "", time.Unix(1, 0).UTC(), "Select,Drop", ""}}, 895 }, 896 { 897 User: "root", 898 Host: "localhost", 899 Query: "UPDATE mysql.tables_priv SET table_priv = 'References,Index' WHERE User = 'tester';", 900 Expected: []sql.Row{{types.OkResult{ 901 RowsAffected: 1, 902 InsertID: 0, 903 Info: plan.UpdateInfo{ 904 Matched: 1, 905 Updated: 1, 906 Warnings: 0, 907 }, 908 }}}, 909 }, 910 { 911 User: "root", 912 Host: "localhost", 913 Query: "SELECT * FROM mysql.tables_priv;", 914 Expected: []sql.Row{{"localhost", "mydb", "tester", "test", "", time.Unix(1, 0).UTC(), "References,Index", ""}}, 915 }, 916 }, 917 }, 918 { 919 Name: "GRANT Procedure and function privileges reflect in mysql.procs_priv", 920 SetUpScript: []string{ 921 "CREATE USER tester1@localhost;", 922 "CREATE USER tester2@localhost;", 923 "GRANT EXECUTE ON PROCEDURE mydb.proc1 TO tester1@localhost;", 924 "GRANT GRANT OPTION ON PROCEDURE mydb.proc1 TO tester1@localhost;", 925 "GRANT ALTER ROUTINE ON PROCEDURE mydb.proc2 TO tester1@localhost;", 926 "GRANT GRANT OPTION ON PROCEDURE mydb.proc1 TO tester2@localhost;", 927 }, 928 Assertions: []UserPrivilegeTestAssertion{ 929 { 930 User: "root", 931 Host: "localhost", 932 Query: "SELECT Routine_name,Routine_type,proc_priv from mysql.procs_priv WHERE User = 'tester1'", 933 Expected: []sql.Row{ 934 {"proc1", "PROCEDURE", "Grant,Execute"}, 935 {"proc2", "PROCEDURE", "Alter Routine"}, 936 }, 937 }, 938 { 939 User: "root", 940 Host: "localhost", 941 Query: "SELECT Routine_name,Routine_type,proc_priv from mysql.procs_priv WHERE User = 'tester2'", 942 Expected: []sql.Row{{"proc1", "PROCEDURE", "Grant"}}, 943 }, 944 { 945 User: "tester1", 946 Host: "localhost", 947 Query: "GRANT Execute ON PROCEDURE mydb.proc1 TO tester2@localhost", 948 Expected: []sql.Row{{types.NewOkResult(0)}}, 949 }, 950 { 951 User: "tester2", 952 Host: "localhost", 953 Query: "GRANT Execute ON PROCEDURE mydb.proc2 TO tester1@localhost", 954 ExpectedErrStr: "command denied to user 'tester2'@'localhost'", 955 }, 956 }, 957 }, 958 { 959 Name: "GRANT Procedure and function privileges reflect in mysql.procs_priv", 960 SetUpScript: []string{ 961 "CREATE USER tester1@localhost;", 962 "CREATE USER tester2@localhost;", 963 "GRANT EXECUTE ON PROCEDURE mydb.proc1 TO tester1@localhost;", 964 "GRANT GRANT OPTION ON PROCEDURE mydb.proc1 TO tester1@localhost;", 965 "GRANT ALTER ROUTINE ON PROCEDURE mydb.proc2 TO tester1@localhost;", 966 "GRANT GRANT OPTION ON PROCEDURE mydb.proc2 TO tester2@localhost;", 967 "GRANT EXECUTE ON PROCEDURE mydb.proc2 TO tester2@localhost;", 968 "REVOKE EXECUTE ON PROCEDURE mydb.proc1 FROM tester1@localhost;", 969 "REVOKE ALTER ROUTINE ON PROCEDURE mydb.proc2 FROM tester1@localhost;", 970 "REVOKE ALTER ROUTINE ON PROCEDURE mydb.proc2 FROM tester2@localhost;", // Should be no-op. 971 }, 972 Assertions: []UserPrivilegeTestAssertion{ 973 { 974 User: "root", 975 Host: "localhost", 976 Query: "SELECT Routine_name,Routine_type,proc_priv from mysql.procs_priv WHERE User = 'tester1'", 977 Expected: []sql.Row{{"proc1", "PROCEDURE", "Grant"}}, 978 }, 979 { 980 User: "root", 981 Host: "localhost", 982 Query: "SELECT Routine_name,Routine_type,proc_priv from mysql.procs_priv WHERE User = 'tester2'", 983 Expected: []sql.Row{sql.Row{"proc2", "PROCEDURE", "Grant,Execute"}}, 984 }, 985 }, 986 }, 987 { 988 Name: "GRANT function privileges errors", 989 SetUpScript: []string{ 990 "CREATE USER tester1@localhost;", 991 }, 992 Assertions: []UserPrivilegeTestAssertion{ 993 { 994 User: "root", 995 Host: "localhost", 996 Query: "GRANT GRANT OPTION ON FUNCTION mydb.func1 TO tester1@localhost;", 997 ExpectedErrStr: "fine grain function permissions currently unsupported", 998 }, 999 { 1000 User: "root", 1001 Host: "localhost", 1002 Query: "GRANT EXECUTE ON FUNCTION mydb.func1 TO tester1@localhost;", 1003 ExpectedErrStr: "fine grain function permissions currently unsupported", 1004 }, 1005 { 1006 User: "root", 1007 Host: "localhost", 1008 Query: "GRANT ALTER ROUTINE ON FUNCTION mydb.func1 TO tester1@localhost;", 1009 ExpectedErrStr: "fine grain function permissions currently unsupported", 1010 }, 1011 }, 1012 }, 1013 { 1014 Name: "Basic revoke SELECT privilege", 1015 SetUpScript: []string{ 1016 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1017 "INSERT INTO test VALUES (1), (2), (3);", 1018 "CREATE USER tester@localhost;", 1019 "GRANT SELECT ON *.* TO tester@localhost;", 1020 }, 1021 Assertions: []UserPrivilegeTestAssertion{ 1022 { 1023 User: "tester", 1024 Host: "localhost", 1025 Query: "SELECT * FROM test;", 1026 Expected: []sql.Row{{1}, {2}, {3}}, 1027 }, 1028 { 1029 User: "root", 1030 Host: "localhost", 1031 Query: "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';", 1032 Expected: []sql.Row{{"tester", "localhost", "Y"}}, 1033 }, 1034 { 1035 User: "root", 1036 Host: "localhost", 1037 Query: "REVOKE SELECT ON *.* FROM tester@localhost;", 1038 Expected: []sql.Row{{types.NewOkResult(0)}}, 1039 }, 1040 { 1041 User: "tester", 1042 Host: "localhost", 1043 Query: "SELECT * FROM test;", 1044 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 1045 }, 1046 { 1047 User: "root", 1048 Host: "localhost", 1049 Query: "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';", 1050 Expected: []sql.Row{{"tester", "localhost", "N"}}, 1051 }, 1052 }, 1053 }, 1054 { 1055 Name: "Basic revoke all global static privileges", 1056 SetUpScript: []string{ 1057 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1058 "INSERT INTO test VALUES (1), (2), (3);", 1059 "CREATE USER tester@localhost;", 1060 "GRANT ALL ON *.* TO tester@localhost;", 1061 }, 1062 Assertions: []UserPrivilegeTestAssertion{ 1063 { 1064 User: "tester", 1065 Host: "localhost", 1066 Query: "INSERT INTO test VALUES (4);", 1067 Expected: []sql.Row{{types.NewOkResult(1)}}, 1068 }, 1069 { 1070 User: "tester", 1071 Host: "localhost", 1072 Query: "SELECT * FROM test;", 1073 Expected: []sql.Row{{1}, {2}, {3}, {4}}, 1074 }, 1075 { 1076 User: "root", 1077 Host: "localhost", 1078 Query: "SELECT User, Host, Select_priv, Insert_priv FROM mysql.user WHERE User = 'tester';", 1079 Expected: []sql.Row{{"tester", "localhost", "Y", "Y"}}, 1080 }, 1081 { 1082 User: "root", 1083 Host: "localhost", 1084 Query: "REVOKE ALL ON *.* FROM tester@localhost;", 1085 Expected: []sql.Row{{types.NewOkResult(0)}}, 1086 }, 1087 { 1088 User: "tester", 1089 Host: "localhost", 1090 Query: "SELECT * FROM test;", 1091 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 1092 }, 1093 { 1094 User: "tester", 1095 Host: "localhost", 1096 Query: "INSERT INTO test VALUES (5);", 1097 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 1098 }, 1099 { 1100 User: "root", 1101 Host: "localhost", 1102 Query: "SELECT User, Host, Select_priv, Insert_priv FROM mysql.user WHERE User = 'tester';", 1103 Expected: []sql.Row{{"tester", "localhost", "N", "N"}}, 1104 }, 1105 }, 1106 }, 1107 { 1108 Name: "Basic role creation", 1109 SetUpScript: []string{ 1110 "CREATE ROLE test_role;", 1111 }, 1112 Assertions: []UserPrivilegeTestAssertion{ 1113 { 1114 User: "root", 1115 Host: "localhost", 1116 Query: "SELECT User, Host, account_locked FROM mysql.user WHERE User = 'test_role';", 1117 Expected: []sql.Row{{"test_role", "%", "Y"}}, 1118 }, 1119 }, 1120 }, 1121 { 1122 Name: "Grant Role with SELECT Privilege", 1123 SetUpScript: []string{ 1124 "SET @@GLOBAL.activate_all_roles_on_login = true;", 1125 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1126 "INSERT INTO test VALUES (1), (2), (3);", 1127 "CREATE USER tester@localhost;", 1128 "CREATE ROLE test_role;", 1129 "GRANT SELECT ON *.* TO test_role;", 1130 }, 1131 Assertions: []UserPrivilegeTestAssertion{ 1132 { 1133 User: "tester", 1134 Host: "localhost", 1135 Query: "SELECT * FROM test;", 1136 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 1137 }, 1138 { 1139 User: "root", 1140 Host: "localhost", 1141 Query: "SELECT COUNT(*) FROM mysql.role_edges;", 1142 Expected: []sql.Row{{0}}, 1143 }, 1144 { 1145 User: "root", 1146 Host: "localhost", 1147 Query: "GRANT test_role TO tester@localhost;", 1148 Expected: []sql.Row{{types.NewOkResult(0)}}, 1149 }, 1150 { 1151 User: "root", 1152 Host: "localhost", 1153 Query: "SELECT * FROM mysql.role_edges;", 1154 Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}}, 1155 }, 1156 { 1157 User: "tester", 1158 Host: "localhost", 1159 Query: "SELECT * FROM test;", 1160 Expected: []sql.Row{{1}, {2}, {3}}, 1161 }, 1162 { 1163 User: "root", 1164 Host: "localhost", 1165 Query: "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';", 1166 Expected: []sql.Row{{"tester", "localhost", "N"}}, 1167 }, 1168 }, 1169 }, 1170 { 1171 Name: "Revoke role currently granted to a user", 1172 SetUpScript: []string{ 1173 "SET @@GLOBAL.activate_all_roles_on_login = true;", 1174 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1175 "INSERT INTO test VALUES (1), (2), (3);", 1176 "CREATE USER tester@localhost;", 1177 "CREATE ROLE test_role;", 1178 "GRANT SELECT ON *.* TO test_role;", 1179 "GRANT test_role TO tester@localhost;", 1180 }, 1181 Assertions: []UserPrivilegeTestAssertion{ 1182 { 1183 User: "tester", 1184 Host: "localhost", 1185 Query: "SELECT * FROM test;", 1186 Expected: []sql.Row{{1}, {2}, {3}}, 1187 }, 1188 { 1189 User: "root", 1190 Host: "localhost", 1191 Query: "SELECT * FROM mysql.role_edges;", 1192 Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}}, 1193 }, 1194 { 1195 User: "root", 1196 Host: "localhost", 1197 Query: "REVOKE test_role FROM tester@localhost;", 1198 Expected: []sql.Row{{types.NewOkResult(0)}}, 1199 }, 1200 { 1201 User: "tester", 1202 Host: "localhost", 1203 Query: "SELECT * FROM test;", 1204 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 1205 }, 1206 { 1207 User: "root", 1208 Host: "localhost", 1209 Query: "SELECT COUNT(*) FROM mysql.role_edges;", 1210 Expected: []sql.Row{{0}}, 1211 }, 1212 { 1213 User: "root", 1214 Host: "localhost", 1215 Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';", 1216 Expected: []sql.Row{{1}}, 1217 }, 1218 { 1219 User: "root", 1220 Host: "localhost", 1221 Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';", 1222 Expected: []sql.Row{{1}}, 1223 }, 1224 }, 1225 }, 1226 { 1227 Name: "Drop role currently granted to a user", 1228 SetUpScript: []string{ 1229 "SET @@GLOBAL.activate_all_roles_on_login = true;", 1230 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1231 "INSERT INTO test VALUES (1), (2), (3);", 1232 "CREATE USER tester@localhost;", 1233 "CREATE ROLE test_role;", 1234 "GRANT SELECT ON *.* TO test_role;", 1235 "GRANT test_role TO tester@localhost;", 1236 }, 1237 Assertions: []UserPrivilegeTestAssertion{ 1238 { 1239 User: "tester", 1240 Host: "localhost", 1241 Query: "SELECT * FROM test;", 1242 Expected: []sql.Row{{1}, {2}, {3}}, 1243 }, 1244 { 1245 User: "root", 1246 Host: "localhost", 1247 Query: "SELECT * FROM mysql.role_edges;", 1248 Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}}, 1249 }, 1250 { 1251 User: "root", 1252 Host: "localhost", 1253 Query: "DROP ROLE test_role;", 1254 Expected: []sql.Row{{types.NewOkResult(0)}}, 1255 }, 1256 { 1257 User: "tester", 1258 Host: "localhost", 1259 Query: "SELECT * FROM test;", 1260 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 1261 }, 1262 { 1263 User: "root", 1264 Host: "localhost", 1265 Query: "SELECT COUNT(*) FROM mysql.role_edges;", 1266 Expected: []sql.Row{{0}}, 1267 }, 1268 { 1269 User: "root", 1270 Host: "localhost", 1271 Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';", 1272 Expected: []sql.Row{{0}}, 1273 }, 1274 { // Ensure nothing wonky happened like the user was deleted as well 1275 User: "root", 1276 Host: "localhost", 1277 Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';", 1278 Expected: []sql.Row{{1}}, 1279 }, 1280 { 1281 User: "root", 1282 Host: "localhost", 1283 Query: "DROP ROLE test_role;", 1284 ExpectedErr: sql.ErrRoleDeletionFailure, 1285 }, 1286 { 1287 User: "root", 1288 Host: "localhost", 1289 Query: "DROP ROLE IF EXISTS test_role;", 1290 Expected: []sql.Row{{types.NewOkResult(0)}}, 1291 }, 1292 }, 1293 }, 1294 { 1295 Name: "Drop user with role currently granted", 1296 SetUpScript: []string{ 1297 "SET @@GLOBAL.activate_all_roles_on_login = true;", 1298 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1299 "INSERT INTO test VALUES (1), (2), (3);", 1300 "CREATE USER tester@localhost;", 1301 "CREATE ROLE test_role;", 1302 "GRANT SELECT ON *.* TO test_role;", 1303 "GRANT test_role TO tester@localhost;", 1304 }, 1305 Assertions: []UserPrivilegeTestAssertion{ 1306 { 1307 User: "root", 1308 Host: "localhost", 1309 Query: "SELECT * FROM mysql.role_edges;", 1310 Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}}, 1311 }, 1312 { 1313 User: "root", 1314 Host: "localhost", 1315 Query: "DROP USER tester@localhost;", 1316 Expected: []sql.Row{{types.NewOkResult(0)}}, 1317 }, 1318 { 1319 User: "root", 1320 Host: "localhost", 1321 Query: "SELECT COUNT(*) FROM mysql.role_edges;", 1322 Expected: []sql.Row{{0}}, 1323 }, 1324 { 1325 User: "root", 1326 Host: "localhost", 1327 Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';", 1328 Expected: []sql.Row{{0}}, 1329 }, 1330 { // Ensure nothing wonky happened like the role was deleted as well 1331 User: "root", 1332 Host: "localhost", 1333 Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';", 1334 Expected: []sql.Row{{1}}, 1335 }, 1336 { 1337 User: "root", 1338 Host: "localhost", 1339 Query: "DROP USER tester@localhost;", 1340 ExpectedErr: sql.ErrUserDeletionFailure, 1341 }, 1342 { 1343 User: "root", 1344 Host: "localhost", 1345 Query: "DROP USER IF EXISTS tester@localhost;", 1346 Expected: []sql.Row{{types.NewOkResult(0)}}, 1347 }, 1348 }, 1349 }, 1350 { 1351 Name: "Show grants on root account", 1352 Assertions: []UserPrivilegeTestAssertion{ 1353 { 1354 User: "root", 1355 Host: "localhost", 1356 Query: "SHOW GRANTS;", 1357 Expected: []sql.Row{{"GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, " + 1358 "FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, " + 1359 "EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, " + 1360 "ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, CREATE ROLE, DROP ROLE ON *.* TO " + 1361 "`root`@`localhost` WITH GRANT OPTION"}}, 1362 }, 1363 }, 1364 }, 1365 { 1366 Name: "Show grants on a user from the root account", 1367 SetUpScript: []string{ 1368 "CREATE USER tester@localhost;", 1369 "GRANT SELECT ON *.* TO tester@localhost;", 1370 "CREATE ROLE test_role1;", 1371 "CREATE ROLE test_role2;", 1372 "GRANT INSERT ON *.* TO test_role1;", 1373 "GRANT REFERENCES ON *.* TO test_role2;", 1374 "GRANT test_role1 TO tester@localhost;", 1375 "GRANT test_role2 TO tester@localhost;", 1376 }, 1377 Assertions: []UserPrivilegeTestAssertion{ 1378 { 1379 User: "root", 1380 Host: "localhost", 1381 Query: "SHOW GRANTS FOR tester@localhost;", 1382 Expected: []sql.Row{ 1383 {"GRANT SELECT ON *.* TO `tester`@`localhost`"}, 1384 {"GRANT `test_role1`@`%`, `test_role2`@`%` TO `tester`@`localhost`"}, 1385 }, 1386 }, 1387 { 1388 User: "root", 1389 Host: "localhost", 1390 Query: "GRANT UPDATE ON *.* TO tester@localhost WITH GRANT OPTION;", 1391 Expected: []sql.Row{{types.NewOkResult(0)}}, 1392 }, 1393 { 1394 User: "root", 1395 Host: "localhost", 1396 Query: "SHOW GRANTS FOR tester@localhost;", 1397 Expected: []sql.Row{ 1398 {"GRANT SELECT, UPDATE ON *.* TO `tester`@`localhost` WITH GRANT OPTION"}, 1399 {"GRANT `test_role1`@`%`, `test_role2`@`%` TO `tester`@`localhost`"}, 1400 }, 1401 }, 1402 { 1403 User: "tester", 1404 Host: "localhost", 1405 Query: "SHOW GRANTS;", 1406 Expected: []sql.Row{ 1407 {"GRANT SELECT, UPDATE ON *.* TO `tester`@`localhost` WITH GRANT OPTION"}, 1408 {"GRANT `test_role1`@`%`, `test_role2`@`%` TO `tester`@`localhost`"}, 1409 }, 1410 }, 1411 }, 1412 }, 1413 { 1414 Name: "show user with no grants", 1415 SetUpScript: []string{ 1416 "CREATE USER tester@localhost;", 1417 }, 1418 Assertions: []UserPrivilegeTestAssertion{ 1419 { 1420 User: "root", 1421 Host: "localhost", 1422 Query: "SHOW GRANTS FOR tester@localhost;", 1423 Expected: []sql.Row{ 1424 {"GRANT USAGE ON *.* TO `tester`@`localhost`"}, 1425 }, 1426 }, 1427 }, 1428 }, 1429 { 1430 Name: "show grants with multiple global grants", 1431 SetUpScript: []string{ 1432 "CREATE USER tester@localhost;", 1433 "GRANT SELECT ON *.* to tester@localhost", 1434 "GRANT INSERT ON *.* to tester@localhost", 1435 }, 1436 Assertions: []UserPrivilegeTestAssertion{ 1437 { 1438 User: "root", 1439 Host: "localhost", 1440 Query: "SHOW GRANTS FOR tester@localhost;", 1441 Expected: []sql.Row{ 1442 {"GRANT SELECT, INSERT ON *.* TO `tester`@`localhost`"}, 1443 }, 1444 }, 1445 }, 1446 }, 1447 { 1448 Name: "show grants at various scopes", 1449 SetUpScript: []string{ 1450 "CREATE USER tester@localhost;", 1451 "GRANT SELECT ON *.* to tester@localhost", 1452 "GRANT SELECT ON db.* to tester@localhost", 1453 "GRANT SELECT ON db.tbl to tester@localhost", 1454 }, 1455 Assertions: []UserPrivilegeTestAssertion{ 1456 { 1457 User: "root", 1458 Host: "localhost", 1459 Query: "SHOW GRANTS FOR tester@localhost;", 1460 Expected: []sql.Row{ 1461 {"GRANT SELECT ON *.* TO `tester`@`localhost`"}, 1462 {"GRANT SELECT ON `db`.* TO `tester`@`localhost`"}, 1463 {"GRANT SELECT ON `db`.`tbl` TO `tester`@`localhost`"}, 1464 }, 1465 }, 1466 }, 1467 }, 1468 { 1469 Name: "show grants at only some scopes", 1470 SetUpScript: []string{ 1471 "CREATE USER tester@localhost;", 1472 "GRANT SELECT ON *.* to tester@localhost", 1473 "GRANT SELECT ON db.tbl to tester@localhost", 1474 }, 1475 Assertions: []UserPrivilegeTestAssertion{ 1476 { 1477 User: "root", 1478 Host: "localhost", 1479 Query: "SHOW GRANTS FOR tester@localhost;", 1480 Expected: []sql.Row{ 1481 {"GRANT SELECT ON *.* TO `tester`@`localhost`"}, 1482 {"GRANT SELECT ON `db`.`tbl` TO `tester`@`localhost`"}, 1483 }, 1484 }, 1485 }, 1486 }, 1487 { 1488 Name: "show always shows global USAGE priv regardless of other privs", 1489 SetUpScript: []string{ 1490 "CREATE USER tester@localhost;", 1491 "GRANT SELECT ON db.* to tester@localhost", 1492 "GRANT INSERT ON db1.* to tester@localhost", 1493 "GRANT DELETE ON db2.* to tester@localhost", 1494 "GRANT SELECT ON db.tbl to tester@localhost", 1495 "GRANT INSERT ON db.tbl to tester@localhost", 1496 }, 1497 Assertions: []UserPrivilegeTestAssertion{ 1498 { 1499 User: "root", 1500 Host: "localhost", 1501 Query: "SHOW GRANTS FOR tester@localhost;", 1502 Expected: []sql.Row{ 1503 {"GRANT USAGE ON *.* TO `tester`@`localhost`"}, 1504 {"GRANT SELECT ON `db`.* TO `tester`@`localhost`"}, 1505 {"GRANT INSERT ON `db1`.* TO `tester`@`localhost`"}, 1506 {"GRANT DELETE ON `db2`.* TO `tester`@`localhost`"}, 1507 {"GRANT SELECT, INSERT ON `db`.`tbl` TO `tester`@`localhost`"}, 1508 }, 1509 }, 1510 }, 1511 }, 1512 { 1513 Name: "with grant option works at every scope", 1514 SetUpScript: []string{ 1515 "CREATE USER tester@localhost;", 1516 "GRANT SELECT ON *.* to tester@localhost WITH GRANT OPTION", 1517 "GRANT SELECT ON db.* to tester@localhost WITH GRANT OPTION", 1518 "GRANT SELECT ON db.tbl to tester@localhost WITH GRANT OPTION", 1519 }, 1520 Assertions: []UserPrivilegeTestAssertion{ 1521 { 1522 User: "root", 1523 Host: "localhost", 1524 Query: "SHOW GRANTS FOR tester@localhost;", 1525 Expected: []sql.Row{ 1526 {"GRANT SELECT ON *.* TO `tester`@`localhost` WITH GRANT OPTION"}, 1527 {"GRANT SELECT ON `db`.* TO `tester`@`localhost` WITH GRANT OPTION"}, 1528 {"GRANT SELECT ON `db`.`tbl` TO `tester`@`localhost` WITH GRANT OPTION"}, 1529 }, 1530 }, 1531 }, 1532 }, 1533 { 1534 Name: "adding with grant option applies to existing privileges", 1535 SetUpScript: []string{ 1536 "CREATE USER tester@localhost;", 1537 "GRANT SELECT ON *.* to tester@localhost", 1538 "GRANT INSERT ON *.* to tester@localhost WITH GRANT OPTION", 1539 "GRANT SELECT ON db.* to tester@localhost", 1540 "GRANT INSERT ON db.* to tester@localhost WITH GRANT OPTION", 1541 "GRANT SELECT ON db.tbl to tester@localhost", 1542 "GRANT INSERT ON db.tbl to tester@localhost WITH GRANT OPTION", 1543 }, 1544 Assertions: []UserPrivilegeTestAssertion{ 1545 { 1546 User: "root", 1547 Host: "localhost", 1548 Query: "SHOW GRANTS FOR tester@localhost;", 1549 Expected: []sql.Row{ 1550 {"GRANT SELECT, INSERT ON *.* TO `tester`@`localhost` WITH GRANT OPTION"}, 1551 {"GRANT SELECT, INSERT ON `db`.* TO `tester`@`localhost` WITH GRANT OPTION"}, 1552 {"GRANT SELECT, INSERT ON `db`.`tbl` TO `tester`@`localhost` WITH GRANT OPTION"}, 1553 }, 1554 }, 1555 }, 1556 }, 1557 { 1558 Name: "SHOW DATABASES shows `mysql` database", 1559 SetUpScript: []string{ 1560 "CREATE USER testuser;", 1561 }, 1562 Assertions: []UserPrivilegeTestAssertion{ 1563 { 1564 User: "root", 1565 Host: "localhost", 1566 Query: "SELECT user FROM mysql.user;", 1567 Expected: []sql.Row{ 1568 {"root"}, 1569 {"testuser"}, 1570 }, 1571 }, 1572 { 1573 User: "root", 1574 Host: "localhost", 1575 Query: "SELECT USER();", 1576 Expected: []sql.Row{ 1577 {"root@localhost"}, 1578 }, 1579 }, 1580 { 1581 User: "root", 1582 Host: "localhost", 1583 Query: "SHOW DATABASES", 1584 Expected: []sql.Row{ 1585 {"information_schema"}, 1586 {"mydb"}, 1587 {"mysql"}, 1588 }, 1589 }, 1590 }, 1591 }, 1592 { 1593 Name: "Anonymous User", 1594 SetUpScript: []string{ 1595 "CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY, v1 BIGINT);", 1596 "CREATE TABLE mydb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT);", 1597 "INSERT INTO mydb.test VALUES (0, 0), (1, 1);", 1598 "INSERT INTO mydb.test2 VALUES (0, 1), (1, 2);", 1599 "CREATE USER 'rand_user'@'localhost';", 1600 "CREATE USER ''@'%';", 1601 "GRANT SELECT ON mydb.test TO 'rand_user'@'localhost';", 1602 "GRANT SELECT ON mydb.test2 TO ''@'%';", 1603 }, 1604 Assertions: []UserPrivilegeTestAssertion{ 1605 { 1606 User: "rand_user", 1607 Host: "localhost", 1608 Query: "SELECT * FROM mydb.test;", 1609 Expected: []sql.Row{ 1610 {0, 0}, 1611 {1, 1}, 1612 }, 1613 }, 1614 { 1615 User: "rand_user", 1616 Host: "localhost", 1617 Query: "SELECT * FROM mydb.test2;", 1618 ExpectedErr: sql.ErrTableAccessDeniedForUser, 1619 }, 1620 { 1621 User: "rand_user", 1622 Host: "non_existent_host", 1623 Query: "SELECT * FROM mydb.test;", 1624 ExpectedErr: sql.ErrTableAccessDeniedForUser, 1625 }, 1626 { 1627 User: "rand_user", 1628 Host: "non_existent_host", 1629 Query: "SELECT * FROM mydb.test2;", 1630 Expected: []sql.Row{ 1631 {0, 1}, 1632 {1, 2}, 1633 }, 1634 }, 1635 { 1636 User: "non_existent_user", 1637 Host: "non_existent_host", 1638 Query: "SELECT * FROM mydb.test;", 1639 ExpectedErr: sql.ErrTableAccessDeniedForUser, 1640 }, 1641 { 1642 User: "non_existent_user", 1643 Host: "non_existent_host", 1644 Query: "SELECT * FROM mydb.test2;", 1645 Expected: []sql.Row{ 1646 {0, 1}, 1647 {1, 2}, 1648 }, 1649 }, 1650 { 1651 User: "", 1652 Host: "%", 1653 Query: "SELECT * FROM mydb.test;", 1654 ExpectedErr: sql.ErrTableAccessDeniedForUser, 1655 }, 1656 { 1657 User: "", 1658 Host: "%", 1659 Query: "SELECT * FROM mydb.test2;", 1660 Expected: []sql.Row{ 1661 {0, 1}, 1662 {1, 2}, 1663 }, 1664 }, 1665 }, 1666 }, 1667 { 1668 Name: "IPv4 Loopback == localhost", 1669 SetUpScript: []string{ 1670 "CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY, v1 BIGINT);", 1671 "CREATE TABLE mydb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT);", 1672 "INSERT INTO mydb.test VALUES (0, 0), (1, 1);", 1673 "INSERT INTO mydb.test2 VALUES (0, 1), (1, 2);", 1674 "CREATE USER 'rand_user1'@'localhost';", 1675 "CREATE USER 'rand_user2'@'127.0.0.1';", 1676 "GRANT SELECT ON mydb.test TO 'rand_user1'@'localhost';", 1677 "GRANT SELECT ON mydb.test2 TO 'rand_user2'@'127.0.0.1';", 1678 }, 1679 Assertions: []UserPrivilegeTestAssertion{ 1680 { 1681 User: "rand_user1", 1682 Host: "localhost", 1683 Query: "SELECT * FROM mydb.test;", 1684 Expected: []sql.Row{ 1685 {0, 0}, 1686 {1, 1}, 1687 }, 1688 }, 1689 { 1690 User: "rand_user1", 1691 Host: "127.0.0.1", 1692 Query: "SELECT * FROM mydb.test;", 1693 Expected: []sql.Row{ 1694 {0, 0}, 1695 {1, 1}, 1696 }, 1697 }, 1698 { 1699 User: "rand_user1", 1700 Host: "54.244.85.252", 1701 Query: "SELECT * FROM mydb.test;", 1702 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 1703 }, 1704 { 1705 User: "rand_user2", 1706 Host: "localhost", 1707 Query: "SELECT * FROM mydb.test2;", 1708 Expected: []sql.Row{ 1709 {0, 1}, 1710 {1, 2}, 1711 }, 1712 }, 1713 { 1714 User: "rand_user2", 1715 Host: "127.0.0.1", 1716 Query: "SELECT * FROM mydb.test2;", 1717 Expected: []sql.Row{ 1718 {0, 1}, 1719 {1, 2}, 1720 }, 1721 }, 1722 { 1723 User: "rand_user2", 1724 Host: "54.244.85.252", 1725 Query: "SELECT * FROM mydb.test2;", 1726 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 1727 }, 1728 }, 1729 }, 1730 { 1731 Name: "DROP USER without a host designation", 1732 SetUpScript: []string{ 1733 "CREATE USER admin;", 1734 }, 1735 Assertions: []UserPrivilegeTestAssertion{ 1736 { 1737 User: "root", 1738 Host: "localhost", 1739 Query: "SELECT user FROM mysql.user", 1740 Expected: []sql.Row{ 1741 {"root"}, 1742 {"admin"}, 1743 }, 1744 }, 1745 { 1746 User: "root", 1747 Host: "localhost", 1748 Query: "DROP USER admin;", 1749 Expected: []sql.Row{{types.NewOkResult(0)}}, 1750 }, 1751 { 1752 User: "root", 1753 Host: "localhost", 1754 Query: "SELECT user FROM mysql.user", 1755 Expected: []sql.Row{ 1756 {"root"}, 1757 }, 1758 }, 1759 }, 1760 }, 1761 { 1762 Name: "information_schema.columns table 'privileges' column gets correct values", 1763 SetUpScript: []string{ 1764 "CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))", 1765 "CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))", 1766 "CREATE USER tester@localhost;", 1767 }, 1768 Assertions: []UserPrivilegeTestAssertion{ 1769 { 1770 User: "tester", 1771 Host: "localhost", 1772 Query: "SELECT count(*) FROM inFORmation_ScHeMa.columns where table_schema = 'mydb' and table_name = 'test';", 1773 Expected: []sql.Row{{0}}, 1774 }, 1775 { 1776 User: "root", 1777 Host: "localhost", 1778 Query: "GRANT INSERT ON mydb.test TO tester@localhost;", 1779 Expected: []sql.Row{{types.NewOkResult(0)}}, 1780 }, 1781 { 1782 User: "tester", 1783 Host: "localhost", 1784 Query: "SELECT column_name, privileges FROM information_schema.columns where table_schema = 'mydb' and table_name = 'test'", 1785 Expected: []sql.Row{{"pk", "insert"}, {"c", "insert"}, {"p", "insert"}}, 1786 }, 1787 { 1788 User: "root", 1789 Host: "localhost", 1790 Query: "GRANT SELECT ON mydb.* TO tester@localhost;", 1791 Expected: []sql.Row{{types.NewOkResult(0)}}, 1792 }, 1793 { 1794 User: "tester", 1795 Host: "localhost", 1796 Query: "SELECT column_name, privileges FROM information_schema.columns where table_schema = 'mydb' and table_name = 'test'", 1797 Expected: []sql.Row{{"pk", "insert,select"}, {"c", "insert,select"}, {"p", "insert,select"}}, 1798 }, 1799 { 1800 User: "root", 1801 Host: "localhost", 1802 Query: "GRANT UPDATE ON mydb.checks TO tester@localhost;", 1803 Expected: []sql.Row{{types.NewOkResult(0)}}, 1804 }, 1805 { 1806 User: "tester", 1807 Host: "localhost", 1808 Query: "select table_name, column_name, privileges from information_schema.columns where table_schema = 'mydb' and table_name = 'checks';", 1809 Expected: []sql.Row{{"checks", "a", "select,update"}, {"checks", "b", "select,update"}, {"checks", "c", "select,update"}}, 1810 }, 1811 { 1812 User: "tester", 1813 Host: "localhost", 1814 Query: "SELECT count(*) FROM information_schema.columns where table_schema = 'information_schema' and table_name = 'columns'", 1815 Expected: []sql.Row{{22}}, 1816 }, 1817 { 1818 User: "root", 1819 Host: "localhost", 1820 Query: "select table_name, column_name, privileges from information_schema.columns where table_schema = 'mydb' and table_name = 'checks';", 1821 Expected: []sql.Row{{"checks", "a", "insert,references,select,update"}, {"checks", "b", "insert,references,select,update"}, {"checks", "c", "insert,references,select,update"}}, 1822 }, 1823 }, 1824 }, 1825 { 1826 Name: "information_schema.column_statistics shows columns with privileges only", 1827 SetUpScript: []string{ 1828 "CREATE TABLE two (i bigint primary key, j bigint, key(j))", 1829 "INSERT INTO two VALUES (1, 4), (2, 5), (3, 6)", 1830 "CREATE TABLE one (f double primary key)", 1831 "INSERT INTO one VALUES (1.25), (45.25), (7.5), (10.5)", 1832 "ANALYZE TABLE one", 1833 "ANALYZE TABLE two", 1834 "CREATE USER tester@localhost;", 1835 }, 1836 Assertions: []UserPrivilegeTestAssertion{ 1837 { 1838 User: "root", 1839 Host: "localhost", 1840 Query: "GRANT SELECT ON mydb.one TO tester@localhost;", 1841 Expected: []sql.Row{{types.NewOkResult(0)}}, 1842 }, 1843 { 1844 User: "tester", 1845 Host: "localhost", 1846 Query: "SELECT table_name, column_name FROM information_schema.column_statistics where schema_name = 'mydb';", 1847 Expected: []sql.Row{ 1848 {"one", "f"}, 1849 }, 1850 }, 1851 { 1852 User: "root", 1853 Host: "localhost", 1854 Query: "GRANT SELECT ON mydb.two TO tester@localhost;", 1855 Expected: []sql.Row{{types.NewOkResult(0)}}, 1856 }, 1857 { 1858 User: "tester", 1859 Host: "localhost", 1860 Query: "SELECT table_name, column_name FROM information_schema.column_statistics where schema_name = 'mydb';", 1861 Expected: []sql.Row{ 1862 {"one", "f"}, 1863 {"two", "i"}, 1864 {"two", "j"}, 1865 }, 1866 }, 1867 }, 1868 }, 1869 { 1870 Name: "information_schema.statistics shows tables with privileges only", 1871 SetUpScript: []string{ 1872 "CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))", 1873 "CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))", 1874 "CREATE USER tester@localhost;", 1875 }, 1876 Assertions: []UserPrivilegeTestAssertion{ 1877 { 1878 User: "tester", 1879 Host: "localhost", 1880 Query: "SELECT count(*) FROM information_schema.statistics where table_schema = 'mydb';", 1881 Expected: []sql.Row{{0}}, 1882 }, 1883 { 1884 User: "root", 1885 Host: "localhost", 1886 Query: "GRANT INSERT ON mydb.checks TO tester@localhost;", 1887 Expected: []sql.Row{{types.NewOkResult(0)}}, 1888 }, 1889 { 1890 User: "tester", 1891 Host: "localhost", 1892 Query: "select table_name, column_name, index_name from information_schema.statistics where table_schema = 'mydb';", 1893 Expected: []sql.Row{{"checks", "a", "PRIMARY"}}, 1894 }, 1895 }, 1896 }, 1897 { 1898 Name: "basic tests on information_schema.SCHEMA_PRIVILEGES table", 1899 SetUpScript: []string{ 1900 "CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))", 1901 "CREATE USER tester@localhost;", 1902 "CREATE USER admin@localhost;", 1903 }, 1904 Assertions: []UserPrivilegeTestAssertion{ 1905 { 1906 User: "root", 1907 Host: "localhost", 1908 Query: "select * from information_schema.schema_privileges;", 1909 Expected: []sql.Row{}, 1910 }, 1911 { 1912 User: "root", 1913 Host: "localhost", 1914 Query: "GRANT INSERT, REFERENCES ON mydb.* TO tester@localhost;", 1915 Expected: []sql.Row{{types.NewOkResult(0)}}, 1916 }, 1917 { 1918 User: "root", 1919 Host: "localhost", 1920 Query: "GRANT UPDATE, GRANT OPTION ON mydb.* TO admin@localhost;", 1921 Expected: []sql.Row{{types.NewOkResult(0)}}, 1922 }, 1923 { 1924 User: "root", 1925 Host: "localhost", 1926 Query: "select * from information_schema.schema_privileges order by privilege_type, is_grantable;", 1927 Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "REFERENCES", "NO"}, {"'admin'@'localhost'", "def", "mydb", "UPDATE", "YES"}}, 1928 }, 1929 { 1930 User: "tester", 1931 Host: "localhost", 1932 Query: "select * from information_schema.schema_privileges order by privilege_type, is_grantable;", 1933 Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "REFERENCES", "NO"}}, 1934 }, 1935 { 1936 User: "admin", 1937 Host: "localhost", 1938 Query: "select * from information_schema.schema_privileges order by privilege_type, is_grantable;", 1939 Expected: []sql.Row{{"'admin'@'localhost'", "def", "mydb", "UPDATE", "YES"}}, 1940 }, 1941 { 1942 User: "root", 1943 Host: "localhost", 1944 Query: "GRANT SELECT ON mysql.* TO admin@localhost;", 1945 Expected: []sql.Row{{types.NewOkResult(0)}}, 1946 }, 1947 { 1948 User: "admin", 1949 Host: "localhost", 1950 Query: "select * from information_schema.schema_privileges order by privilege_type, is_grantable;", 1951 Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "REFERENCES", "NO"}, {"'admin'@'localhost'", "def", "mysql", "SELECT", "NO"}, {"'admin'@'localhost'", "def", "mydb", "UPDATE", "YES"}}, 1952 }, 1953 }, 1954 }, 1955 { 1956 Name: "basic tests on information_schema.TABLE_PRIVILEGES table", 1957 SetUpScript: []string{ 1958 "CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))", 1959 "CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))", 1960 "CREATE USER tester@localhost;", 1961 "CREATE USER admin@localhost;", 1962 }, 1963 Assertions: []UserPrivilegeTestAssertion{ 1964 { 1965 User: "root", 1966 Host: "localhost", 1967 Query: "select * from information_schema.table_privileges;", 1968 Expected: []sql.Row{}, 1969 }, 1970 { 1971 User: "root", 1972 Host: "localhost", 1973 Query: "GRANT INSERT ON mydb.checks TO tester@localhost;", 1974 Expected: []sql.Row{{types.NewOkResult(0)}}, 1975 }, 1976 { 1977 User: "root", 1978 Host: "localhost", 1979 Query: "GRANT UPDATE, GRANT OPTION ON mydb.test TO tester@localhost;", 1980 Expected: []sql.Row{{types.NewOkResult(0)}}, 1981 }, 1982 { 1983 User: "root", 1984 Host: "localhost", 1985 Query: "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*root*/", 1986 Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "checks", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "test", "UPDATE", "YES"}}, 1987 }, 1988 { 1989 User: "tester", 1990 Host: "localhost", 1991 Query: "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*tester*/", 1992 Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "checks", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "test", "UPDATE", "YES"}}, 1993 }, 1994 { 1995 User: "admin", 1996 Host: "localhost", 1997 Query: "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*admin1*/", 1998 Expected: []sql.Row{}, 1999 }, 2000 { 2001 User: "root", 2002 Host: "localhost", 2003 Query: "GRANT SELECT ON mysql.* TO admin@localhost;", 2004 Expected: []sql.Row{{types.NewOkResult(0)}}, 2005 }, 2006 { 2007 User: "admin", 2008 Host: "localhost", 2009 Query: "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*admin2*/", 2010 Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "checks", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "test", "UPDATE", "YES"}}, 2011 }, 2012 }, 2013 }, 2014 { 2015 Name: "basic tests on information_schema.USER_PRIVILEGES table", 2016 SetUpScript: []string{ 2017 "CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))", 2018 "CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))", 2019 "CREATE USER tester@localhost;", 2020 "CREATE USER admin@localhost;", 2021 }, 2022 Assertions: []UserPrivilegeTestAssertion{ 2023 { 2024 User: "root", 2025 Host: "localhost", 2026 Query: "select * from information_schema.user_privileges order by privilege_type LIMIT 4;/*root*/", 2027 Expected: []sql.Row{{"'root'@'localhost'", "def", "ALTER", "YES"}, 2028 {"'root'@'localhost'", "def", "ALTER ROUTINE", "YES"}, 2029 {"'root'@'localhost'", "def", "CREATE", "YES"}, 2030 {"'root'@'localhost'", "def", "CREATE ROLE", "YES"}}, 2031 }, 2032 { 2033 User: "root", 2034 Host: "localhost", 2035 Query: "GRANT INSERT ON *.* TO tester@localhost;", 2036 Expected: []sql.Row{{types.NewOkResult(0)}}, 2037 }, 2038 { 2039 User: "tester", 2040 Host: "localhost", 2041 Query: "select * from information_schema.user_privileges order by privilege_type, is_grantable;/*tester1*/", 2042 Expected: []sql.Row{{"'tester'@'localhost'", "def", "INSERT", "NO"}}, 2043 }, 2044 { 2045 User: "root", 2046 Host: "localhost", 2047 Query: "GRANT UPDATE, GRANT OPTION ON *.* TO tester@localhost;", 2048 Expected: []sql.Row{{types.NewOkResult(0)}}, 2049 }, 2050 { 2051 User: "tester", 2052 Host: "localhost", 2053 Query: "select * from information_schema.user_privileges order by privilege_type, is_grantable;/*tester2*/", 2054 Expected: []sql.Row{{"'tester'@'localhost'", "def", "INSERT", "YES"}, {"'tester'@'localhost'", "def", "UPDATE", "YES"}}, 2055 }, 2056 { 2057 User: "admin", 2058 Host: "localhost", 2059 Query: "select * from information_schema.user_privileges order by privilege_type, is_grantable;/*admin*/", 2060 Expected: []sql.Row{}, 2061 }, 2062 }, 2063 }, 2064 { 2065 Name: "basic tests on information_schema.USER_ATTRIBUTES table", 2066 SetUpScript: []string{ 2067 "CREATE USER tester@localhost;", 2068 // TODO: attributes info is ignored in sqlparser 2069 `CREATE USER admin@localhost ATTRIBUTE '{"fname": "Josh", "lname": "Scott"}';`, 2070 "GRANT UPDATE ON mysql.* TO admin@localhost;", 2071 }, 2072 Assertions: []UserPrivilegeTestAssertion{ 2073 { 2074 User: "root", 2075 Host: "localhost", 2076 Query: "select * from information_schema.user_attributes order by user;/*root*/", 2077 Expected: []sql.Row{{"admin", "localhost", nil}, 2078 {"root", "localhost", nil}, 2079 {"tester", "localhost", nil}}, 2080 }, 2081 { 2082 User: "admin", 2083 Host: "localhost", 2084 Query: "select * from information_schema.user_attributes order by user;/*admin*/", 2085 Expected: []sql.Row{{"admin", "localhost", nil}, 2086 {"root", "localhost", nil}, 2087 {"tester", "localhost", nil}}, 2088 }, 2089 { 2090 User: "tester", 2091 Host: "localhost", 2092 Query: "select * from information_schema.user_attributes order by user;/*tester*/", 2093 Expected: []sql.Row{{"tester", "localhost", nil}}, 2094 }, 2095 }, 2096 }, 2097 { 2098 Name: "basic privilege tests on information_schema.ROUTINES and PARAMETERS tables", 2099 SetUpScript: []string{ 2100 "CREATE USER tester@localhost;", 2101 "CREATE PROCEDURE testabc(IN x DOUBLE, IN y FLOAT, OUT abc DECIMAL(5,1)) SELECT x*y INTO abc", 2102 }, 2103 Assertions: []UserPrivilegeTestAssertion{ 2104 { 2105 User: "tester", 2106 Host: "localhost", 2107 Query: "select count(*) from information_schema.routines where routine_name = 'testabc'/*tester1*/;", 2108 Expected: []sql.Row{{0}}, 2109 }, 2110 { 2111 User: "tester", 2112 Host: "localhost", 2113 Query: "select count(*) from information_schema.parameters where specific_name = 'testabc'/*tester1*/;", 2114 Expected: []sql.Row{{0}}, 2115 }, 2116 { 2117 User: "root", 2118 Host: "localhost", 2119 Query: "GRANT CREATE ROUTINE ON mydb.* TO tester@localhost;", 2120 Expected: []sql.Row{{types.NewOkResult(0)}}, 2121 }, 2122 { 2123 User: "tester", 2124 Host: "localhost", 2125 Query: "select count(*) from information_schema.routines where routine_name = 'testabc';", 2126 Expected: []sql.Row{{1}}, 2127 }, 2128 { 2129 User: "tester", 2130 Host: "localhost", 2131 Query: "select count(*) from information_schema.parameters where specific_name = 'testabc';", 2132 Expected: []sql.Row{{3}}, 2133 }, 2134 }, 2135 }, 2136 } 2137 2138 // NoopPlaintextPlugin is used to authenticate plaintext user plugins 2139 type NoopPlaintextPlugin struct{} 2140 2141 var _ mysql_db.PlaintextAuthPlugin = &NoopPlaintextPlugin{} 2142 2143 func (p *NoopPlaintextPlugin) Authenticate(db *mysql_db.MySQLDb, user string, userEntry *mysql_db.User, pass string) (bool, error) { 2144 return pass == "right-password", nil 2145 } 2146 2147 // ServerAuthTests test the server authentication system. These tests always have the root account available, and the 2148 // root account is used with any queries in the SetUpScript, along as being set to the context passed to SetUpFunc. 2149 var ServerAuthTests = []ServerAuthenticationTest{ 2150 { 2151 Name: "ALTER USER can change passwords", 2152 Assertions: []ServerAuthenticationTestAssertion{ 2153 // Create test users, privileges, etc 2154 { 2155 Username: "root", 2156 Password: "", 2157 Query: "CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY);", 2158 ExpectedErr: false, 2159 }, { 2160 // Create a user with CREATE USER privileges 2161 Username: "root", 2162 Password: "", 2163 Query: "CREATE USER `createUserUser`@`localhost` IDENTIFIED BY '';", 2164 ExpectedErr: false, 2165 }, { 2166 Username: "root", 2167 Password: "", 2168 Query: "GRANT CREATE USER ON *.* TO `createUserUser`@`localhost`;", 2169 ExpectedErr: false, 2170 }, { 2171 // Create a user with UPDATE privileges on the mysql database 2172 Username: "root", 2173 Password: "", 2174 Query: "CREATE USER `updateUser`@`localhost` IDENTIFIED BY '';", 2175 ExpectedErr: false, 2176 }, { 2177 Username: "root", 2178 Password: "", 2179 Query: "GRANT UPDATE ON mysql.* TO `updateUser`@`localhost`;", 2180 ExpectedErr: false, 2181 }, { 2182 // Create a regular user named user1 with SELECT privileges 2183 Username: "root", 2184 Password: "", 2185 Query: "CREATE USER `user1`@`localhost` IDENTIFIED BY '';", 2186 ExpectedErr: false, 2187 }, { 2188 Username: "root", 2189 Password: "", 2190 Query: "GRANT SELECT ON *.* TO `user1`@`localhost`;", 2191 ExpectedErr: false, 2192 }, { 2193 // Create a regular user named user2 with SELECT privileges 2194 Username: "root", 2195 Password: "", 2196 Query: "CREATE USER `user2`@`localhost` IDENTIFIED BY '';", 2197 ExpectedErr: false, 2198 }, { 2199 Username: "root", 2200 Password: "", 2201 Query: "GRANT SELECT ON *.* TO `user2`@`localhost`;", 2202 ExpectedErr: false, 2203 }, 2204 2205 // When IF EXISTS is specified, an error isn't returned if the user doesn't exist 2206 { 2207 Username: "root", 2208 Password: "", 2209 Query: "ALTER USER IF EXISTS nobody@localhost IDENTIFIED BY 'password';", 2210 ExpectedErr: false, 2211 }, { 2212 Username: "root", 2213 Password: "", 2214 Query: "ALTER USER nobody@localhost IDENTIFIED BY 'password';", 2215 ExpectedErr: true, 2216 ExpectedErrStr: "Error 1105 (HY000): Operation ALTER USER failed for 'nobody'@'localhost'", 2217 }, 2218 2219 // RANDOM PASSWORD is not supported yet, so an error should be returned 2220 { 2221 Username: "root", 2222 Password: "", 2223 Query: "ALTER USER user2@localhost IDENTIFIED BY RANDOM PASSWORD;", 2224 ExpectedErr: true, 2225 ExpectedErrStr: "Error 1105 (HY000): random password generation is not currently supported; " + 2226 "you can request support at https://github.com/dolthub/dolt/issues/new", 2227 }, 2228 2229 // root super user can change other account passwords 2230 { 2231 Username: "root", 2232 Password: "", 2233 Query: "ALTER USER `user1`@`localhost` IDENTIFIED BY 'password1';", 2234 ExpectedErr: false, 2235 }, { 2236 Username: "user1", 2237 Password: "", 2238 Query: "SELECT * FROM mydb.test;", 2239 ExpectedErr: true, 2240 }, { 2241 Username: "user1", 2242 Password: "password1", 2243 Query: "SELECT * FROM mydb.test;", 2244 ExpectedErr: false, 2245 }, 2246 2247 // Accounts with the CREATE USER privilege can change other account passwords 2248 { 2249 Username: "createUserUser", 2250 Password: "", 2251 Query: "ALTER USER `user1`@`localhost` IDENTIFIED BY 'password2';", 2252 ExpectedErr: false, 2253 }, { 2254 Username: "user1", 2255 Password: "", 2256 Query: "SELECT * FROM mydb.test;", 2257 ExpectedErr: true, 2258 }, { 2259 Username: "user1", 2260 Password: "password2", 2261 Query: "SELECT * FROM mydb.test;", 2262 ExpectedErr: false, 2263 }, 2264 2265 // Accounts with the UPDATE privilege on the mysql db can change other account passwords 2266 { 2267 Username: "updateUser", 2268 Password: "", 2269 Query: "ALTER USER `user2`@`localhost` IDENTIFIED BY 'password3';", 2270 ExpectedErr: false, 2271 }, { 2272 Username: "user2", 2273 Password: "", 2274 Query: "SELECT * FROM mydb.test;", 2275 ExpectedErr: true, 2276 }, { 2277 Username: "user2", 2278 Password: "password3", 2279 Query: "SELECT * FROM mydb.test;", 2280 ExpectedErr: false, 2281 }, 2282 2283 // Accounts can change their own password 2284 { 2285 Username: "user1", 2286 Password: "password2", 2287 Query: "ALTER USER `user1`@`localhost` IDENTIFIED BY 'password4';", 2288 ExpectedErr: false, 2289 }, { 2290 Username: "user1", 2291 Password: "", 2292 Query: "SELECT * FROM mydb.test;", 2293 ExpectedErr: true, 2294 }, { 2295 Username: "user1", 2296 Password: "password4", 2297 Query: "SELECT * FROM mydb.test;", 2298 ExpectedErr: false, 2299 }, 2300 2301 // Accounts CANNOT change another account's password (without the CREATE USER or UPDATE privilege) 2302 { 2303 Username: "user1", 2304 Password: "password2", 2305 Query: "ALTER USER `user2`@`localhost` IDENTIFIED BY 'password5';", 2306 ExpectedErr: true, 2307 }, 2308 }, 2309 }, 2310 { 2311 Name: "DROP USER reports correct string for missing address", 2312 Assertions: []ServerAuthenticationTestAssertion{ 2313 { 2314 Username: "root", 2315 Password: "", 2316 Query: "DROP USER xyz;", 2317 ExpectedErrStr: "Error 1105 (HY000): Operation DROP USER failed for 'xyz'@'%'", 2318 }, 2319 }, 2320 }, 2321 { 2322 Name: "CREATE USER with a random password is not supported", 2323 Assertions: []ServerAuthenticationTestAssertion{ 2324 { 2325 Username: "root", 2326 Password: "", 2327 Query: "CREATE USER foo1@localhost IDENTIFIED BY RANDOM PASSWORD;", 2328 ExpectedErr: true, 2329 ExpectedErrStr: "Error 1105 (HY000): random password generation is not currently supported; " + 2330 "you can request support at https://github.com/dolthub/dolt/issues/new", 2331 }, 2332 }, 2333 }, 2334 { 2335 Name: "CREATE USER with an empty password", 2336 Assertions: []ServerAuthenticationTestAssertion{ 2337 { 2338 Username: "root", 2339 Password: "", 2340 Query: "CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY);", 2341 ExpectedErr: false, 2342 }, 2343 { 2344 Username: "root", 2345 Password: "", 2346 Query: "CREATE USER rand_user@localhost IDENTIFIED BY '';", 2347 ExpectedErr: false, 2348 }, 2349 { 2350 Username: "root", 2351 Password: "", 2352 Query: "GRANT ALL ON *.* TO rand_user@localhost;", 2353 ExpectedErr: false, 2354 }, 2355 { 2356 Username: "rand_user", 2357 Password: "", 2358 Query: "SELECT * FROM mydb.test;", 2359 ExpectedErr: false, 2360 }, 2361 }, 2362 }, 2363 { 2364 Name: "Basic root authentication", 2365 Assertions: []ServerAuthenticationTestAssertion{ 2366 { 2367 Username: "root", 2368 Password: "", 2369 Query: "SELECT * FROM mysql.user;", 2370 ExpectedErr: false, 2371 }, 2372 { 2373 Username: "root", 2374 Password: "pass", 2375 Query: "SELECT * FROM mysql.user;", 2376 ExpectedErr: true, 2377 }, 2378 }, 2379 }, 2380 { 2381 Name: "Create User without plugin specification", 2382 SetUpScript: []string{ 2383 "CREATE USER rand_user@localhost IDENTIFIED BY 'rand_pass';", 2384 "GRANT ALL ON *.* TO rand_user@localhost WITH GRANT OPTION;", 2385 }, 2386 Assertions: []ServerAuthenticationTestAssertion{ 2387 { 2388 Username: "rand_user", 2389 Password: "rand_pass", 2390 Query: "SELECT * FROM mysql.user;", 2391 ExpectedErr: false, 2392 }, 2393 { 2394 Username: "rand_user", 2395 Password: "rand_pass1", 2396 Query: "SELECT * FROM mysql.user;", 2397 ExpectedErr: true, 2398 }, 2399 { 2400 Username: "rand_user", 2401 Password: "", 2402 Query: "SELECT * FROM mysql.user;", 2403 ExpectedErr: true, 2404 }, 2405 { 2406 Username: "rand_use", 2407 Password: "rand_pass", 2408 Query: "SELECT * FROM mysql.user;", 2409 ExpectedErr: true, 2410 }, 2411 }, 2412 }, 2413 { 2414 Name: "Create User with plugin specification", 2415 SetUpScript: []string{ 2416 "CREATE USER ranuse@localhost IDENTIFIED WITH mysql_native_password BY 'ranpas';", 2417 "GRANT ALL ON *.* TO ranuse@localhost WITH GRANT OPTION;", 2418 }, 2419 Assertions: []ServerAuthenticationTestAssertion{ 2420 { 2421 Username: "ranuse", 2422 Password: "ranpas", 2423 Query: "SELECT * FROM mysql.user;", 2424 ExpectedErr: false, 2425 }, 2426 { 2427 Username: "ranuse", 2428 Password: "what", 2429 Query: "SELECT * FROM mysql.user;", 2430 ExpectedErr: true, 2431 }, 2432 { 2433 Username: "ranuse", 2434 Password: "", 2435 Query: "SELECT * FROM mysql.user;", 2436 ExpectedErr: true, 2437 }, 2438 }, 2439 }, 2440 { 2441 Name: "Create User with jwt plugin specification", 2442 SetUpScript: []string{ 2443 "CREATE USER `test-user`@localhost IDENTIFIED WITH authentication_dolt_jwt AS 'jwks=testing,sub=test-user,iss=dolthub.com,aud=some_id';", 2444 "GRANT ALL ON *.* TO `test-user`@localhost WITH GRANT OPTION;", 2445 }, 2446 SetUpFunc: func(ctx *sql.Context, t *testing.T, engine *sqle.Engine) { 2447 plugins := map[string]mysql_db.PlaintextAuthPlugin{"authentication_dolt_jwt": &NoopPlaintextPlugin{}} 2448 engine.EngineAnalyzer().Catalog.MySQLDb.SetPlugins(plugins) 2449 }, 2450 Assertions: []ServerAuthenticationTestAssertion{ 2451 { 2452 Username: "test-user", 2453 Password: "what", 2454 Query: "SELECT * FROM mysql.user;", 2455 ExpectedErr: true, 2456 }, 2457 { 2458 Username: "test-user", 2459 Password: "", 2460 Query: "SELECT * FROM mysql.user;", 2461 ExpectedErr: true, 2462 }, 2463 { 2464 Username: "test-user", 2465 Password: "right-password", 2466 Query: "SELECT * FROM mysql.user;", 2467 ExpectedErr: false, 2468 }, 2469 }, 2470 }, 2471 { 2472 Name: "Adding a Super User directly", 2473 SetUpFunc: func(ctx *sql.Context, t *testing.T, engine *sqle.Engine) { 2474 ed := engine.EngineAnalyzer().Catalog.MySQLDb.Editor() 2475 defer ed.Close() 2476 engine.EngineAnalyzer().Catalog.MySQLDb.AddSuperUser(ed, "bestuser", "localhost", "the_pass") 2477 }, 2478 Assertions: []ServerAuthenticationTestAssertion{ 2479 { 2480 Username: "bestuser", 2481 Password: "the_past", 2482 Query: "SELECT * FROM mysql.user;", 2483 ExpectedErr: true, 2484 }, 2485 { 2486 Username: "bestuser", 2487 Password: "the_pass", 2488 Query: "SELECT * FROM mysql.user;", 2489 ExpectedErr: false, 2490 }, 2491 }, 2492 }, 2493 } 2494 2495 // QuickPrivTests are test that specifically attempt to test as many privileges against as many statements as possible, 2496 // while being as succinct as possible. All tests here could be fully represented as a UserPrivilegeTest, however each 2497 // equivalent test would comparatively take up many more lines. This is intended to have as many tests as possible that 2498 // are as quick to write as possible. 2499 var QuickPrivTests = []QuickPrivilegeTest{ 2500 { 2501 Queries: []string{ 2502 "GRANT SELECT ON *.* TO tester@localhost", 2503 "SELECT * FROM mydb.test", 2504 }, 2505 Expected: []sql.Row{{0, 0}, {1, 1}}, 2506 }, 2507 { 2508 Queries: []string{ 2509 "GRANT SELECT ON mydb.* TO tester@localhost", 2510 "SELECT * FROM mydb.test", 2511 }, 2512 Expected: []sql.Row{{0, 0}, {1, 1}}, 2513 }, 2514 { 2515 Queries: []string{ 2516 "GRANT SELECT ON mydb.* TO tester@localhost", 2517 "SELECT * FROM mydb.test2", 2518 }, 2519 Expected: []sql.Row{{0, 1}, {1, 2}}, 2520 }, 2521 { 2522 Queries: []string{ 2523 "GRANT SELECT ON mydb.test TO tester@localhost", 2524 "SELECT * FROM mydb.test", 2525 }, 2526 Expected: []sql.Row{{0, 0}, {1, 1}}, 2527 }, 2528 { 2529 Queries: []string{ 2530 "GRANT SELECT ON mydb.test TO tester@localhost", 2531 "SELECT * FROM mydb.test2", 2532 }, 2533 ExpectingErr: true, 2534 }, 2535 { 2536 Queries: []string{ 2537 "GRANT SELECT ON otherdb.* TO tester@localhost", 2538 "SELECT * FROM mydb.test", 2539 }, 2540 ExpectingErr: true, 2541 }, 2542 { 2543 Queries: []string{ 2544 "GRANT SELECT ON otherdb.test TO tester@localhost", 2545 "SELECT * FROM mydb.test", 2546 }, 2547 ExpectingErr: true, 2548 }, 2549 { 2550 Queries: []string{ 2551 "GRANT SELECT ON otherdb.test TO tester@localhost", 2552 "SELECT * FROM mydb.test", 2553 }, 2554 ExpectingErr: true, 2555 }, 2556 { 2557 Queries: []string{ 2558 "GRANT SELECT ON *.* TO tester@localhost", 2559 "USE mydb;", 2560 "SHOW TABLES;", 2561 }, 2562 Expected: []sql.Row{{"test"}, {"test2"}}, 2563 }, 2564 { 2565 Queries: []string{ 2566 "GRANT SELECT ON mydb.* TO tester@localhost", 2567 "USE mydb;", 2568 "SHOW TABLES;", 2569 }, 2570 Expected: []sql.Row{{"test"}, {"test2"}}, 2571 }, 2572 { 2573 Queries: []string{ 2574 "GRANT SELECT ON mydb.test TO tester@localhost", 2575 "USE mydb;", 2576 "SHOW TABLES;", 2577 }, 2578 Expected: []sql.Row{{"test"}}, 2579 }, 2580 { 2581 Queries: []string{ 2582 "GRANT SELECT ON mydb.non_exist TO tester@localhost", 2583 "USE mydb;", 2584 "SHOW TABLES;", 2585 }, 2586 Expected: []sql.Row{}, 2587 }, 2588 { 2589 Queries: []string{ 2590 "ALTER TABLE mydb.test ADD COLUMN new_column BIGINT;", 2591 }, 2592 ExpectingErr: true, 2593 }, 2594 { 2595 Queries: []string{ 2596 "GRANT ALTER ON *.* TO tester@localhost", 2597 "ALTER TABLE mydb.test ADD COLUMN new_column BIGINT", 2598 }, 2599 }, 2600 { 2601 Queries: []string{ 2602 "GRANT ALTER ON mydb.* TO tester@localhost", 2603 "ALTER TABLE mydb.test ADD COLUMN new_column BIGINT;", 2604 }, 2605 }, 2606 { 2607 Queries: []string{ 2608 "GRANT ALTER ON mydb.test TO tester@localhost", 2609 "ALTER TABLE mydb.test ADD COLUMN new_column BIGINT;", 2610 }, 2611 }, 2612 { 2613 Queries: []string{ 2614 "ALTER TABLE mydb.test RENAME TO mydb.new_test;", 2615 }, 2616 ExpectingErr: true, 2617 }, 2618 { 2619 Queries: []string{ 2620 "GRANT ALTER ON *.* TO tester@localhost", 2621 "ALTER TABLE mydb.test RENAME TO mydb.new_test;", 2622 }, 2623 ExpectingErr: true, 2624 }, 2625 { 2626 Queries: []string{ 2627 "GRANT ALTER, CREATE, DROP, INSERT ON *.* TO tester@localhost", 2628 "ALTER TABLE mydb.test RENAME TO mydb.new_test;", 2629 }, 2630 }, 2631 { 2632 Queries: []string{ 2633 "GRANT ALTER, CREATE, DROP, INSERT ON mydb.* TO tester@localhost", 2634 "ALTER TABLE mydb.test RENAME TO mydb.new_test;", 2635 }, 2636 }, 2637 { 2638 Queries: []string{ 2639 "GRANT ALTER, CREATE, DROP, INSERT ON mydb.test TO tester@localhost", 2640 "ALTER TABLE mydb.test RENAME TO mydb.new_test;", 2641 }, 2642 ExpectingErr: true, 2643 }, 2644 { 2645 Queries: []string{ 2646 "GRANT ALTER, DROP ON mydb.test TO tester@localhost", 2647 "GRANT CREATE, INSERT ON mydb.new_test TO tester@localhost", 2648 "ALTER TABLE mydb.test RENAME TO mydb.new_test;", 2649 }, 2650 }, 2651 { 2652 Queries: []string{ 2653 "GRANT ALTER ON mydb.test TO tester@localhost", 2654 "GRANT CREATE, INSERT ON mydb.new_test TO tester@localhost", 2655 "ALTER TABLE mydb.test RENAME TO mydb.new_test;", 2656 }, 2657 ExpectingErr: true, 2658 }, 2659 { 2660 Queries: []string{ 2661 "GRANT DROP ON mydb.test TO tester@localhost", 2662 "GRANT CREATE, INSERT ON mydb.new_test TO tester@localhost", 2663 "ALTER TABLE mydb.test RENAME TO mydb.new_test;", 2664 }, 2665 ExpectingErr: true, 2666 }, 2667 { 2668 Queries: []string{ 2669 "GRANT ALTER, DROP ON mydb.test TO tester@localhost", 2670 "GRANT CREATE ON mydb.new_test TO tester@localhost", 2671 "ALTER TABLE mydb.test RENAME TO mydb.new_test;", 2672 }, 2673 ExpectingErr: true, 2674 }, 2675 { 2676 Queries: []string{ 2677 "GRANT ALTER, DROP ON mydb.test TO tester@localhost", 2678 "GRANT INSERT ON mydb.new_test TO tester@localhost", 2679 "ALTER TABLE mydb.test RENAME TO mydb.new_test;", 2680 }, 2681 ExpectingErr: true, 2682 }, 2683 { 2684 Queries: []string{ 2685 "USE mydb;", 2686 "CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;", 2687 "DROP PROCEDURE new_proc;", 2688 }, 2689 ExpectingErr: true, 2690 }, 2691 { 2692 Queries: []string{ 2693 "GRANT ALTER ROUTINE ON *.* TO tester@localhost", 2694 "USE mydb;", 2695 "CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;", 2696 "DROP PROCEDURE new_proc;", 2697 }, 2698 }, 2699 { 2700 Queries: []string{ 2701 "GRANT ALTER ROUTINE ON mydb.* TO tester@localhost", 2702 "USE mydb;", 2703 "CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;", 2704 "DROP PROCEDURE new_proc;", 2705 }, 2706 }, 2707 { 2708 Queries: []string{ 2709 "CREATE DATABASE new_db;", 2710 }, 2711 ExpectingErr: true, 2712 }, 2713 { 2714 Queries: []string{ 2715 "CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);", 2716 }, 2717 ExpectingErr: true, 2718 }, 2719 { 2720 Queries: []string{ 2721 "GRANT CREATE ON *.* TO tester@localhost", 2722 "CREATE DATABASE new_db2;", 2723 "GRANT DROP ON *.* TO tester@localhost", 2724 "drop database new_db2", 2725 }, 2726 }, 2727 { 2728 Queries: []string{ 2729 "GRANT CREATE ON *.* TO tester@localhost", 2730 "CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);", 2731 }, 2732 }, 2733 { 2734 Queries: []string{ 2735 "GRANT CREATE ON mydb.* TO tester@localhost", 2736 "CREATE DATABASE new_db3;", 2737 "GRANT DROP ON *.* TO tester@localhost", 2738 "drop database new_db3", 2739 }, 2740 }, 2741 { 2742 Queries: []string{ 2743 "GRANT CREATE ON mydb.* TO tester@localhost", 2744 "CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);", 2745 }, 2746 }, 2747 { 2748 Queries: []string{ 2749 "CREATE ROLE new_role;", 2750 }, 2751 ExpectingErr: true, 2752 }, 2753 { 2754 Queries: []string{ 2755 "GRANT CREATE ROLE ON *.* TO tester@localhost", 2756 "CREATE ROLE new_role;", 2757 }, 2758 }, 2759 { 2760 Queries: []string{ 2761 "USE mydb;", 2762 "CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;", 2763 }, 2764 ExpectingErr: true, 2765 }, 2766 { 2767 Queries: []string{ 2768 "GRANT CREATE ROUTINE ON *.* TO tester@localhost", 2769 "USE mydb;", 2770 "CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;", 2771 }, 2772 }, 2773 { 2774 Queries: []string{ 2775 "GRANT CREATE ROUTINE ON mydb.* TO tester@localhost", 2776 "USE mydb;", 2777 "CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;", 2778 }, 2779 }, 2780 { 2781 Queries: []string{ 2782 "CREATE USER new_user;", 2783 }, 2784 ExpectingErr: true, 2785 }, 2786 { 2787 Queries: []string{ 2788 "CREATE USER new_user;", 2789 "DROP USER new_user;", 2790 }, 2791 ExpectingErr: true, 2792 }, 2793 { 2794 Queries: []string{ 2795 "GRANT CREATE USER ON *.* TO tester@localhost", 2796 "CREATE USER new_user;", 2797 }, 2798 }, 2799 { 2800 Queries: []string{ 2801 "GRANT CREATE USER ON *.* TO tester@localhost", 2802 "CREATE USER new_user;", 2803 "DROP USER new_user;", 2804 }, 2805 }, 2806 { 2807 Queries: []string{ 2808 "GRANT CREATE USER ON *.* TO tester@localhost", 2809 "CREATE ROLE new_role;", 2810 }, 2811 }, 2812 { 2813 Queries: []string{ 2814 "GRANT CREATE USER ON *.* TO tester@localhost", 2815 "CREATE ROLE new_role;", 2816 "DROP ROLE new_role;", 2817 }, 2818 }, 2819 { 2820 Queries: []string{ 2821 "CREATE VIEW new_view AS SELECT 1;", 2822 }, 2823 ExpectingErr: true, 2824 }, 2825 { 2826 Queries: []string{ 2827 "GRANT CREATE VIEW ON *.* TO tester@localhost", 2828 "CREATE VIEW new_view AS SELECT 1;", 2829 }, 2830 }, 2831 { 2832 Queries: []string{ 2833 "DELETE FROM mydb.test WHERE pk >= 0;", 2834 }, 2835 ExpectingErr: true, 2836 }, 2837 { 2838 Queries: []string{ 2839 "GRANT DELETE ON *.* TO tester@localhost", 2840 "DELETE FROM mydb.test WHERE pk >= 0;", 2841 }, 2842 }, 2843 { 2844 Queries: []string{ 2845 "GRANT DELETE ON mydb.* TO tester@localhost", 2846 "DELETE FROM mydb.test WHERE pk >= 0;", 2847 }, 2848 }, 2849 { 2850 Queries: []string{ 2851 "GRANT DELETE ON mydb.test TO tester@localhost", 2852 "DELETE FROM mydb.test WHERE pk >= 0;", 2853 }, 2854 }, 2855 { 2856 Queries: []string{ 2857 "DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk", 2858 }, 2859 ExpectingErr: true, 2860 }, 2861 { 2862 Queries: []string{ 2863 "GRANT DELETE ON mydb.test TO tester@localhost", 2864 "DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk", 2865 }, 2866 ExpectingErr: true, 2867 }, 2868 { 2869 Queries: []string{ 2870 "GRANT DELETE ON mydb.test2 TO tester@localhost", 2871 "DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk", 2872 }, 2873 ExpectingErr: true, 2874 }, 2875 { 2876 Queries: []string{ 2877 "GRANT DELETE ON mydb.test TO tester@localhost", 2878 "GRANT DELETE ON mydb.test2 TO tester@localhost", 2879 "DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk", 2880 }, 2881 }, 2882 { 2883 Queries: []string{ 2884 "CREATE DATABASE new_db4;", 2885 }, 2886 ExpectingErr: true, 2887 }, 2888 { 2889 Queries: []string{ 2890 "CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);", 2891 "DROP TABLE mydb.new_table;", 2892 }, 2893 ExpectingErr: true, 2894 }, 2895 { 2896 Queries: []string{ 2897 "CREATE VIEW new_view AS SELECT 1;", 2898 "DROP VIEW new_view;", 2899 }, 2900 ExpectingErr: true, 2901 }, 2902 { 2903 Queries: []string{ 2904 "GRANT DROP ON *.* TO tester@localhost", 2905 "CREATE DATABASE new_db5;", 2906 "GRANT DROP ON *.* TO tester@localhost", 2907 "DROP DATABASE new_db5;", 2908 }, 2909 }, 2910 { 2911 Queries: []string{ 2912 "GRANT DROP ON *.* TO tester@localhost", 2913 "CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);", 2914 "DROP TABLE mydb.new_table;", 2915 }, 2916 }, 2917 { 2918 Queries: []string{ 2919 "GRANT DROP ON *.* TO tester@localhost", 2920 "CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);", 2921 "CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);", 2922 "DROP TABLE mydb.new_table1, mydb.new_table2;", 2923 }, 2924 }, 2925 { 2926 Queries: []string{ 2927 "GRANT DROP ON *.* TO tester@localhost", 2928 "CREATE VIEW new_view AS SELECT 1;", 2929 "DROP VIEW new_view;", 2930 }, 2931 }, 2932 { 2933 Queries: []string{ 2934 "GRANT DROP ON mydb.* TO tester@localhost", 2935 "CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);", 2936 "DROP TABLE mydb.new_table;", 2937 }, 2938 }, 2939 { 2940 Queries: []string{ 2941 "GRANT DROP ON mydb.* TO tester@localhost", 2942 "CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);", 2943 "CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);", 2944 "DROP TABLE mydb.new_table1, mydb.new_table2;", 2945 }, 2946 }, 2947 { 2948 Queries: []string{ 2949 "GRANT DROP ON mydb.new_table TO tester@localhost", 2950 "CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);", 2951 "DROP TABLE mydb.new_table;", 2952 }, 2953 }, 2954 { 2955 Queries: []string{ 2956 "GRANT DROP ON mydb.new_table1 TO tester@localhost", 2957 "CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);", 2958 "CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);", 2959 "DROP TABLE mydb.new_table1, mydb.new_table2;", 2960 }, 2961 ExpectingErr: true, 2962 }, 2963 { 2964 Queries: []string{ 2965 "GRANT DROP ON mydb.new_table2 TO tester@localhost", 2966 "CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);", 2967 "CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);", 2968 "DROP TABLE mydb.new_table1, mydb.new_table2;", 2969 }, 2970 ExpectingErr: true, 2971 }, 2972 { 2973 Queries: []string{ 2974 "GRANT DROP ON mydb.new_table1 TO tester@localhost", 2975 "GRANT DROP ON mydb.new_table2 TO tester@localhost", 2976 "CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);", 2977 "CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);", 2978 "DROP TABLE mydb.new_table1, mydb.new_table2;", 2979 }, 2980 }, 2981 { 2982 Queries: []string{ 2983 "CREATE ROLE new_role;", 2984 "DROP ROLE new_role;", 2985 }, 2986 ExpectingErr: true, 2987 }, 2988 { 2989 Queries: []string{ 2990 "GRANT DROP ROLE ON *.* TO tester@localhost", 2991 "CREATE ROLE new_role;", 2992 "DROP ROLE new_role;", 2993 }, 2994 }, 2995 { 2996 Queries: []string{ 2997 "CREATE INDEX new_idx ON mydb.test (v1);", 2998 }, 2999 ExpectingErr: true, 3000 }, 3001 { 3002 Queries: []string{ 3003 "CREATE INDEX new_idx ON mydb.test (v1);", 3004 "DROP INDEX new_idx ON mydb.test;", 3005 }, 3006 ExpectingErr: true, 3007 }, 3008 { 3009 Queries: []string{ 3010 "GRANT INDEX ON *.* TO tester@localhost", 3011 "CREATE INDEX new_idx ON mydb.test (v1);", 3012 }, 3013 }, 3014 { 3015 Queries: []string{ 3016 "GRANT INDEX ON *.* TO tester@localhost", 3017 "CREATE INDEX new_idx ON mydb.test (v1);", 3018 "DROP INDEX new_idx ON mydb.test;", 3019 }, 3020 }, 3021 { 3022 Queries: []string{ 3023 "GRANT INDEX ON mydb.* TO tester@localhost", 3024 "CREATE INDEX new_idx ON mydb.test (v1);", 3025 }, 3026 }, 3027 { 3028 Queries: []string{ 3029 "GRANT INDEX ON mydb.* TO tester@localhost", 3030 "CREATE INDEX new_idx ON mydb.test (v1);", 3031 "DROP INDEX new_idx ON mydb.test;", 3032 }, 3033 }, 3034 { 3035 Queries: []string{ 3036 "GRANT INDEX ON mydb.test TO tester@localhost", 3037 "CREATE INDEX new_idx ON mydb.test (v1);", 3038 }, 3039 }, 3040 { 3041 Queries: []string{ 3042 "GRANT INDEX ON mydb.test TO tester@localhost", 3043 "CREATE INDEX new_idx ON mydb.test (v1);", 3044 "DROP INDEX new_idx ON mydb.test;", 3045 }, 3046 }, 3047 { 3048 Queries: []string{ 3049 "INSERT INTO mydb.test VALUES (9, 9);", 3050 }, 3051 ExpectingErr: true, 3052 }, 3053 { 3054 Queries: []string{ 3055 "GRANT INSERT ON *.* TO tester@localhost", 3056 "INSERT INTO mydb.test VALUES (9, 9);", 3057 }, 3058 }, 3059 { 3060 Queries: []string{ 3061 "GRANT INSERT ON mydb.* TO tester@localhost", 3062 "INSERT INTO mydb.test VALUES (9, 9);", 3063 }, 3064 }, 3065 { 3066 Queries: []string{ 3067 "GRANT INSERT ON mydb.test TO tester@localhost", 3068 "INSERT INTO mydb.test VALUES (9, 9);", 3069 }, 3070 }, 3071 { 3072 Queries: []string{ 3073 "CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;", 3074 }, 3075 ExpectingErr: true, 3076 }, 3077 { 3078 Queries: []string{ 3079 "CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;", 3080 "DROP TRIGGER new_trig;", 3081 }, 3082 ExpectingErr: true, 3083 }, 3084 { 3085 Queries: []string{ 3086 "GRANT TRIGGER ON *.* TO tester@localhost", 3087 "CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;", 3088 }, 3089 }, 3090 { 3091 Queries: []string{ 3092 "GRANT TRIGGER ON *.* TO tester@localhost", 3093 "CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;", 3094 "DROP TRIGGER new_trig;", 3095 }, 3096 }, 3097 { 3098 Queries: []string{ 3099 "GRANT TRIGGER ON mydb.* TO tester@localhost", 3100 "CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;", 3101 }, 3102 }, 3103 { 3104 Queries: []string{ 3105 "GRANT TRIGGER ON mydb.* TO tester@localhost", 3106 "CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;", 3107 "DROP TRIGGER new_trig;", 3108 }, 3109 }, 3110 { 3111 Queries: []string{ 3112 "UPDATE mydb.test SET v1 = 0;", 3113 }, 3114 ExpectingErr: true, 3115 }, 3116 { 3117 Queries: []string{ 3118 "GRANT UPDATE ON *.* TO tester@localhost", 3119 "UPDATE mydb.test SET v1 = 0;", 3120 }, 3121 }, 3122 { 3123 Queries: []string{ 3124 "GRANT UPDATE ON mydb.* TO tester@localhost", 3125 "UPDATE mydb.test SET v1 = 0;", 3126 }, 3127 }, 3128 { 3129 Queries: []string{ 3130 "GRANT UPDATE ON mydb.test TO tester@localhost", 3131 "UPDATE mydb.test SET v1 = 0;", 3132 }, 3133 }, 3134 { 3135 Queries: []string{ 3136 "FLUSH PRIVILEGES;", 3137 }, 3138 ExpectingErr: true, 3139 }, 3140 { 3141 Queries: []string{ 3142 "GRANT RELOAD ON *.* TO tester@localhost", 3143 "FLUSH PRIVILEGES;", 3144 }, 3145 }, 3146 }