github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/enginetest/privilege_test.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 enginetest 16 17 import ( 18 "testing" 19 20 "github.com/dolthub/go-mysql-server/enginetest" 21 "github.com/dolthub/go-mysql-server/enginetest/queries" 22 "github.com/dolthub/go-mysql-server/enginetest/scriptgen/setup" 23 "github.com/dolthub/go-mysql-server/sql" 24 "github.com/dolthub/go-mysql-server/sql/mysql_db" 25 "github.com/dolthub/go-mysql-server/sql/plan" 26 "github.com/dolthub/go-mysql-server/sql/types" 27 "github.com/stretchr/testify/require" 28 ) 29 30 var revisionDatabasePrivsSetupPostfix = []string{ 31 "call dolt_commit('-Am', 'first commit')", 32 "call dolt_branch('b1')", 33 "use mydb/b1", 34 } 35 36 // The subset of tests in priv_auth_queries.go to run with alternate branch logic. Not all of them are suitable 37 // because they are too difficult to adapt with simple additions to setup 38 var revisionDatabasePrivilegeScriptNames = []string{ 39 "Basic database and table name visibility", 40 "Basic SELECT and INSERT privilege checking", 41 "Table-level privileges exist", 42 "Basic revoke SELECT privilege", 43 "Basic revoke all global static privileges", 44 "Grant Role with SELECT Privilege", 45 "Revoke role currently granted to a user", 46 "Drop role currently granted to a user", 47 "Anonymous User", 48 "IPv4 Loopback == localhost", 49 "information_schema.columns table 'privileges' column gets correct values", 50 "basic tests on information_schema.SCHEMA_PRIVILEGES table", 51 "basic tests on information_schema.TABLE_PRIVILEGES table", 52 } 53 54 // TestRevisionDatabasePrivileges is a spot-check of privilege checking on the original privilege test scripts, 55 // but with a revisioned database as the current db 56 func TestRevisionDatabasePrivileges(t *testing.T) { 57 testsToRun := make(map[string]bool) 58 for _, name := range revisionDatabasePrivilegeScriptNames { 59 testsToRun[name] = true 60 } 61 62 var scripts []queries.UserPrivilegeTest 63 for _, script := range queries.UserPrivTests { 64 if testsToRun[script.Name] { 65 scripts = append(scripts, script) 66 } 67 } 68 69 require.Equal(t, len(scripts), len(testsToRun), 70 "Error in test setup: one or more expected tests not found. "+ 71 "Did the name of a test change?") 72 73 for _, script := range scripts { 74 harness := newDoltHarness(t) 75 harness.configureStats = true 76 harness.Setup(setup.MydbData, setup.MytableData) 77 t.Run(script.Name, func(t *testing.T) { 78 engine := mustNewEngine(t, harness) 79 defer engine.Close() 80 81 ctx := enginetest.NewContext(harness) 82 ctx.NewCtxWithClient(sql.Client{ 83 User: "root", 84 Address: "localhost", 85 }) 86 engine.EngineAnalyzer().Catalog.MySQLDb.AddRootAccount() 87 engine.EngineAnalyzer().Catalog.MySQLDb.SetPersister(&mysql_db.NoopPersister{}) 88 89 for _, statement := range append(script.SetUpScript, revisionDatabasePrivsSetupPostfix...) { 90 if harness.SkipQueryTest(statement) { 91 t.Skip() 92 } 93 enginetest.RunQueryWithContext(t, engine, harness, ctx, statement) 94 } 95 96 for _, assertion := range script.Assertions { 97 if harness.SkipQueryTest(assertion.Query) { 98 t.Skipf("Skipping query %s", assertion.Query) 99 } 100 101 user := assertion.User 102 host := assertion.Host 103 if user == "" { 104 user = "root" 105 } 106 if host == "" { 107 host = "localhost" 108 } 109 ctx := enginetest.NewContextWithClient(harness, sql.Client{ 110 User: user, 111 Address: host, 112 }) 113 ctx.SetCurrentDatabase("mydb/b1") 114 115 if assertion.ExpectedErr != nil { 116 t.Run(assertion.Query, func(t *testing.T) { 117 enginetest.AssertErrWithCtx(t, engine, harness, ctx, assertion.Query, assertion.ExpectedErr) 118 }) 119 } else if assertion.ExpectedErrStr != "" { 120 t.Run(assertion.Query, func(t *testing.T) { 121 enginetest.AssertErrWithCtx(t, engine, harness, ctx, assertion.Query, nil, assertion.ExpectedErrStr) 122 }) 123 } else { 124 t.Run(assertion.Query, func(t *testing.T) { 125 enginetest.TestQueryWithContext(t, ctx, engine, harness, assertion.Query, assertion.Expected, nil, nil) 126 }) 127 } 128 } 129 }) 130 } 131 } 132 133 // Privilege test scripts for revision databases. Due to limitations in test construction, test assertions are always 134 // performed with current db = mydb/b1, write scripts accordingly 135 var DoltOnlyRevisionDbPrivilegeTests = []queries.UserPrivilegeTest{ 136 { 137 Name: "Basic database and table name visibility", 138 SetUpScript: []string{ 139 "use mydb", 140 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 141 "INSERT INTO test VALUES (1);", 142 "call dolt_commit('-Am', 'first commit')", 143 "call dolt_branch('b1')", 144 "use mydb/b1", 145 "CREATE USER tester@localhost;", 146 "CREATE ROLE test_role;", 147 "GRANT SELECT ON mydb.* TO test_role;", 148 }, 149 Assertions: []queries.UserPrivilegeTestAssertion{ 150 { 151 User: "tester", 152 Host: "localhost", 153 Query: "SELECT * FROM test;/*1*/", 154 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 155 }, 156 { 157 User: "tester", 158 Host: "localhost", 159 Query: "SELECT * FROM test2;/*1*/", 160 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 161 }, 162 { 163 User: "root", 164 Host: "localhost", 165 Query: "GRANT SELECT ON mydb.* TO tester@localhost;", 166 Expected: []sql.Row{{types.NewOkResult(0)}}, 167 }, 168 { 169 User: "tester", 170 Host: "localhost", 171 Query: "SELECT * FROM test;/*2*/", 172 Expected: []sql.Row{{1}}, 173 }, 174 { 175 User: "tester", 176 Host: "localhost", 177 Query: "SELECT * FROM test2;/*2*/", 178 ExpectedErr: sql.ErrTableNotFound, 179 }, 180 { 181 User: "root", 182 Host: "localhost", 183 Query: "REVOKE SELECT ON mydb.* FROM tester@localhost;", 184 Expected: []sql.Row{{types.NewOkResult(0)}}, 185 }, 186 { // Ensure we've reverted to initial state (all SELECTs after REVOKEs are doing this) 187 User: "tester", 188 Host: "localhost", 189 Query: "SELECT * FROM test;/*3*/", 190 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 191 }, 192 { 193 User: "tester", 194 Host: "localhost", 195 Query: "SELECT * FROM test2;/*3*/", 196 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 197 }, 198 { 199 User: "root", 200 Host: "localhost", 201 Query: "GRANT SELECT ON mydb.* TO tester@localhost;", 202 Expected: []sql.Row{{types.NewOkResult(0)}}, 203 }, 204 { 205 User: "tester", 206 Host: "localhost", 207 Query: "SELECT * FROM mydb.test;/*4*/", 208 Expected: []sql.Row{{1}}, 209 }, 210 { 211 User: "tester", 212 Host: "localhost", 213 Query: "SELECT * FROM test2;/*4*/", 214 ExpectedErr: sql.ErrTableNotFound, 215 }, 216 { 217 User: "root", 218 Host: "localhost", 219 Query: "REVOKE SELECT ON mydb.* FROM tester@localhost;", 220 Expected: []sql.Row{{types.NewOkResult(0)}}, 221 }, 222 { 223 User: "tester", 224 Host: "localhost", 225 Query: "SELECT * FROM test;/*5*/", 226 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 227 }, 228 { 229 User: "tester", 230 Host: "localhost", 231 Query: "SELECT * FROM test2;/*5*/", 232 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 233 }, 234 { 235 User: "root", 236 Host: "localhost", 237 Query: "GRANT SELECT ON mydb.test TO tester@localhost;", 238 Expected: []sql.Row{{types.NewOkResult(0)}}, 239 }, 240 { 241 User: "tester", 242 Host: "localhost", 243 Query: "SELECT * FROM test;/*6*/", 244 Expected: []sql.Row{{1}}, 245 }, 246 { 247 User: "tester", 248 Host: "localhost", 249 Query: "SELECT * FROM test2;/*6*/", 250 ExpectedErr: sql.ErrTableAccessDeniedForUser, 251 }, 252 { 253 User: "root", 254 Host: "localhost", 255 Query: "REVOKE SELECT ON mydb.test FROM tester@localhost;", 256 Expected: []sql.Row{{types.NewOkResult(0)}}, 257 }, 258 { 259 User: "tester", 260 Host: "localhost", 261 Query: "SELECT * FROM test;/*7*/", 262 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 263 }, 264 { 265 User: "tester", 266 Host: "localhost", 267 Query: "SELECT * FROM test2;/*7*/", 268 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 269 }, 270 { 271 User: "root", 272 Host: "localhost", 273 Query: "GRANT SELECT ON mydb.test2 TO tester@localhost;", 274 Expected: []sql.Row{{types.NewOkResult(0)}}, 275 }, 276 { 277 User: "tester", 278 Host: "localhost", 279 Query: "SELECT * FROM test;/*8*/", 280 ExpectedErr: sql.ErrTableAccessDeniedForUser, 281 }, 282 { 283 User: "tester", 284 Host: "localhost", 285 Query: "SELECT * FROM test2;/*8*/", 286 ExpectedErr: sql.ErrTableNotFound, 287 }, 288 { 289 User: "root", 290 Host: "localhost", 291 Query: "REVOKE SELECT ON mydb.test2 FROM tester@localhost;", 292 Expected: []sql.Row{{types.NewOkResult(0)}}, 293 }, 294 { 295 User: "tester", 296 Host: "localhost", 297 Query: "SELECT * FROM test;/*9*/", 298 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 299 }, 300 { 301 User: "tester", 302 Host: "localhost", 303 Query: "SELECT * FROM test2;/*9*/", 304 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 305 }, 306 { 307 User: "root", 308 Host: "localhost", 309 Query: "GRANT test_role TO tester@localhost;", 310 Expected: []sql.Row{{types.NewOkResult(0)}}, 311 }, 312 { 313 User: "tester", 314 Host: "localhost", 315 Query: "SELECT * FROM test;/*10*/", 316 Expected: []sql.Row{{1}}, 317 }, 318 { 319 User: "tester", 320 Host: "localhost", 321 Query: "SELECT * FROM test2;/*10*/", 322 ExpectedErr: sql.ErrTableNotFound, 323 }, 324 }, 325 }, 326 { 327 Name: "Basic SELECT and INSERT privilege checking", 328 SetUpScript: []string{ 329 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 330 "INSERT INTO test VALUES (1), (2), (3);", 331 "call dolt_commit('-Am', 'first commit');", 332 "call dolt_branch('b1')", 333 "use mydb/b1;", 334 "CREATE USER tester@localhost;", 335 }, 336 Assertions: []queries.UserPrivilegeTestAssertion{ 337 { 338 User: "tester", 339 Host: "localhost", 340 Query: "INSERT INTO test VALUES (4);", 341 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 342 }, 343 { 344 User: "root", 345 Host: "localhost", 346 Query: "GRANT INSERT ON mydb.* TO tester@localhost;", 347 Expected: []sql.Row{{types.NewOkResult(0)}}, 348 }, 349 { 350 User: "tester", 351 Host: "localhost", 352 Query: "INSERT INTO test VALUES (4);", 353 Expected: []sql.Row{{types.NewOkResult(1)}}, 354 }, 355 { 356 User: "tester", 357 Host: "localhost", 358 Query: "SELECT * FROM test;", 359 ExpectedErr: sql.ErrPrivilegeCheckFailed, 360 }, 361 { 362 User: "root", 363 Host: "localhost", 364 Query: "SELECT * FROM test;", 365 Expected: []sql.Row{{1}, {2}, {3}, {4}}, 366 }, 367 { 368 User: "root", 369 Host: "localhost", 370 Query: "GRANT SELECT ON mydb.* TO tester@localhost;", 371 Expected: []sql.Row{{types.NewOkResult(0)}}, 372 }, 373 { 374 User: "tester", 375 Host: "localhost", 376 Query: "SELECT * FROM test;", 377 Expected: []sql.Row{{1}, {2}, {3}, {4}}, 378 }, 379 }, 380 }, 381 { 382 Name: "Basic UPDATE privilege checking", 383 SetUpScript: []string{ 384 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 385 "INSERT INTO test VALUES (1), (2), (3);", 386 "call dolt_commit('-Am', 'first commit');", 387 "call dolt_branch('b1')", 388 "use mydb/b1;", 389 "CREATE USER tester@localhost;", 390 }, 391 Assertions: []queries.UserPrivilegeTestAssertion{ 392 { 393 User: "tester", 394 Host: "localhost", 395 Query: "UPDATE test set pk = 4 where pk = 3;", 396 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 397 }, 398 { 399 User: "root", 400 Host: "localhost", 401 Query: "GRANT UPDATE ON mydb.* TO tester@localhost;", 402 Expected: []sql.Row{{types.NewOkResult(0)}}, 403 }, 404 { 405 User: "tester", 406 Host: "localhost", 407 Query: "INSERT INTO test VALUES (4);", 408 ExpectedErr: sql.ErrPrivilegeCheckFailed, 409 }, 410 { 411 User: "tester", 412 Host: "localhost", 413 Query: "UPDATE test set pk = 4 where pk = 3;", 414 Expected: []sql.Row{{types.OkResult{ 415 RowsAffected: 1, 416 Info: plan.UpdateInfo{ 417 Matched: 1, 418 Updated: 1, 419 }, 420 }}}, 421 }, 422 { 423 User: "tester", 424 Host: "localhost", 425 Query: "SELECT * FROM test;", 426 ExpectedErr: sql.ErrPrivilegeCheckFailed, 427 }, 428 { 429 User: "root", 430 Host: "localhost", 431 Query: "SELECT * FROM test;", 432 Expected: []sql.Row{{1}, {2}, {4}}, 433 }, 434 }, 435 }, 436 { 437 Name: "Basic DELETE privilege checking", 438 SetUpScript: []string{ 439 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 440 "INSERT INTO test VALUES (1), (2), (3);", 441 "call dolt_commit('-Am', 'first commit');", 442 "call dolt_branch('b1')", 443 "use mydb/b1;", 444 "CREATE USER tester@localhost;", 445 }, 446 Assertions: []queries.UserPrivilegeTestAssertion{ 447 { 448 User: "tester", 449 Host: "localhost", 450 Query: "DELETE from test where pk = 3;", 451 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 452 }, 453 { 454 User: "root", 455 Host: "localhost", 456 Query: "GRANT DELETE ON mydb.* TO tester@localhost;", 457 Expected: []sql.Row{{types.NewOkResult(0)}}, 458 }, 459 { 460 User: "tester", 461 Host: "localhost", 462 Query: "INSERT INTO test VALUES (4);", 463 ExpectedErr: sql.ErrPrivilegeCheckFailed, 464 }, 465 { 466 User: "tester", 467 Host: "localhost", 468 Query: "DELETE from test where pk = 3;", 469 Expected: []sql.Row{{types.NewOkResult(1)}}, 470 }, 471 { 472 User: "tester", 473 Host: "localhost", 474 Query: "SELECT * FROM test;", 475 ExpectedErr: sql.ErrPrivilegeCheckFailed, 476 }, 477 { 478 User: "root", 479 Host: "localhost", 480 Query: "SELECT * FROM test;", 481 Expected: []sql.Row{{1}, {2}}, 482 }, 483 }, 484 }, 485 { 486 Name: "Basic CREATE TABLE privilege checking", 487 SetUpScript: []string{ 488 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 489 "call dolt_commit('-Am', 'first commit');", 490 "call dolt_branch('b1')", 491 "use mydb/b1;", 492 "CREATE USER tester@localhost;", 493 }, 494 Assertions: []queries.UserPrivilegeTestAssertion{ 495 { 496 User: "tester", 497 Host: "localhost", 498 Query: "CREATE TABLE t2 (a int primary key);", 499 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 500 }, 501 { 502 User: "root", 503 Host: "localhost", 504 Query: "GRANT CREATE ON mydb.* TO tester@localhost;", 505 Expected: []sql.Row{{types.NewOkResult(0)}}, 506 }, 507 { 508 User: "tester", 509 Host: "localhost", 510 Query: "CREATE TABLE t2 (a int primary key);", 511 Expected: []sql.Row{{types.NewOkResult(0)}}, 512 }, 513 { 514 User: "tester", 515 Host: "localhost", 516 Query: "show tables;", 517 Expected: []sql.Row{{"mytable"}, {"myview"}, {"test"}, {"t2"}}, 518 }, 519 }, 520 }, 521 { 522 Name: "Basic DROP TABLE privilege checking", 523 SetUpScript: []string{ 524 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 525 "INSERT INTO test VALUES (1), (2), (3);", 526 "call dolt_commit('-Am', 'first commit');", 527 "call dolt_branch('b1')", 528 "use mydb/b1;", 529 "CREATE USER tester@localhost;", 530 }, 531 Assertions: []queries.UserPrivilegeTestAssertion{ 532 { 533 User: "tester", 534 Host: "localhost", 535 Query: "DROP TABLE test;", 536 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 537 }, 538 { 539 User: "root", 540 Host: "localhost", 541 Query: "GRANT DROP ON mydb.* TO tester@localhost;", 542 Expected: []sql.Row{{types.NewOkResult(0)}}, 543 }, 544 { 545 User: "tester", 546 Host: "localhost", 547 Query: "DROP TABLE TEST", 548 Expected: []sql.Row{{types.NewOkResult(0)}}, 549 }, 550 { 551 User: "tester", 552 Host: "localhost", 553 Query: "show tables;", 554 Expected: []sql.Row{{"mytable"}, {"myview"}}, 555 }, 556 }, 557 }, 558 { 559 Name: "Basic ALTER TABLE privilege checking", 560 SetUpScript: []string{ 561 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 562 "INSERT INTO test VALUES (1), (2), (3);", 563 "call dolt_commit('-Am', 'first commit');", 564 "call dolt_branch('b1')", 565 "use mydb/b1;", 566 "CREATE USER tester@localhost;", 567 }, 568 Assertions: []queries.UserPrivilegeTestAssertion{ 569 { 570 User: "tester", 571 Host: "localhost", 572 Query: "ALTER TABLE test add column a int;", 573 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 574 }, 575 { 576 User: "root", 577 Host: "localhost", 578 Query: "GRANT ALTER ON mydb.* TO tester@localhost;", 579 Expected: []sql.Row{{types.NewOkResult(0)}}, 580 }, 581 { 582 User: "tester", 583 Host: "localhost", 584 Query: "ALTER TABLE test add column a int;", 585 Expected: []sql.Row{{types.NewOkResult(0)}}, 586 }, 587 { 588 User: "tester", 589 Host: "localhost", 590 Query: "desc test;", 591 Expected: []sql.Row{ 592 {"pk", "bigint", "NO", "PRI", nil, ""}, 593 {"a", "int", "YES", "", nil, ""}, 594 }, 595 }, 596 }, 597 }, 598 { 599 Name: "Basic INDEX privilege checking", 600 SetUpScript: []string{ 601 "CREATE TABLE test (pk BIGINT PRIMARY KEY, a int);", 602 "INSERT INTO test VALUES (1,1), (2,2), (3,3);", 603 "call dolt_commit('-Am', 'first commit');", 604 "call dolt_branch('b1')", 605 "use mydb/b1;", 606 "CREATE USER tester@localhost;", 607 }, 608 Assertions: []queries.UserPrivilegeTestAssertion{ 609 { 610 User: "tester", 611 Host: "localhost", 612 Query: "create index t1 on test(a) ;", 613 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 614 }, 615 { 616 User: "root", 617 Host: "localhost", 618 Query: "GRANT select ON mydb.* TO tester@localhost;", 619 Expected: []sql.Row{{types.NewOkResult(0)}}, 620 }, 621 { 622 User: "tester", 623 Host: "localhost", 624 Query: "create index t1 on test(a) ;", 625 ExpectedErr: sql.ErrPrivilegeCheckFailed, 626 }, 627 { 628 User: "root", 629 Host: "localhost", 630 Query: "GRANT index ON mydb.* TO tester@localhost;", 631 Expected: []sql.Row{{types.NewOkResult(0)}}, 632 }, 633 { 634 User: "tester", 635 Host: "localhost", 636 Query: "create index t1 on test(a) ;", 637 Expected: []sql.Row{{types.NewOkResult(0)}}, 638 }, 639 { 640 User: "tester", 641 Host: "localhost", 642 Query: "desc test;", 643 Expected: []sql.Row{ 644 {"pk", "bigint", "NO", "PRI", nil, ""}, 645 {"a", "int", "YES", "MUL", nil, ""}, 646 }, 647 }, 648 { 649 User: "root", 650 Host: "localhost", 651 Query: "REVOKE index ON mydb.* FROM tester@localhost;", 652 Expected: []sql.Row{{types.NewOkResult(0)}}, 653 }, 654 { 655 User: "tester", 656 Host: "localhost", 657 Query: "drop index t1 on test;", 658 ExpectedErr: sql.ErrPrivilegeCheckFailed, 659 }, 660 { 661 User: "root", 662 Host: "localhost", 663 Query: "GRANT index ON mydb.* TO tester@localhost;", 664 Expected: []sql.Row{{types.NewOkResult(0)}}, 665 }, 666 { 667 User: "tester", 668 Host: "localhost", 669 Query: "drop index t1 on test;", 670 Expected: []sql.Row{{types.NewOkResult(0)}}, 671 }, 672 { 673 User: "tester", 674 Host: "localhost", 675 Query: "desc test;", 676 Expected: []sql.Row{ 677 {"pk", "bigint", "NO", "PRI", nil, ""}, 678 {"a", "int", "YES", "", nil, ""}, 679 }, 680 }, 681 }, 682 }, 683 { 684 Name: "Basic constraint privilege checking", 685 SetUpScript: []string{ 686 "CREATE TABLE test (pk BIGINT PRIMARY KEY, a int);", 687 "INSERT INTO test VALUES (1,1), (2,2), (3,3);", 688 "call dolt_commit('-Am', 'first commit');", 689 "call dolt_branch('b1')", 690 "use mydb/b1;", 691 "CREATE USER tester@localhost;", 692 }, 693 Assertions: []queries.UserPrivilegeTestAssertion{ 694 { 695 User: "tester", 696 Host: "localhost", 697 Query: "alter table test add constraint CHECK (NULL = NULL);", 698 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 699 }, 700 { 701 User: "root", 702 Host: "localhost", 703 Query: "GRANT select ON mydb.* TO tester@localhost;", 704 Expected: []sql.Row{{types.NewOkResult(0)}}, 705 }, 706 { 707 User: "tester", 708 Host: "localhost", 709 Query: "alter table test add constraint CHECK (NULL = NULL);", 710 ExpectedErr: sql.ErrPrivilegeCheckFailed, 711 }, 712 { 713 User: "root", 714 Host: "localhost", 715 Query: "GRANT alter ON mydb.* TO tester@localhost;", 716 Expected: []sql.Row{{types.NewOkResult(0)}}, 717 }, 718 { 719 User: "tester", 720 Host: "localhost", 721 Query: "alter table test add constraint chk1 CHECK (a < 10);", 722 Expected: []sql.Row{{types.NewOkResult(0)}}, 723 }, 724 { 725 User: "tester", 726 Host: "localhost", 727 Query: "show create table test;", 728 Expected: []sql.Row{ 729 {"test", "CREATE TABLE `test` (\n" + 730 " `pk` bigint NOT NULL,\n" + 731 " `a` int,\n" + 732 " PRIMARY KEY (`pk`),\n" + 733 " CONSTRAINT `chk1` CHECK ((`a` < 10))\n" + 734 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 735 }, 736 }, 737 { 738 User: "root", 739 Host: "localhost", 740 Query: "REVOKE alter ON mydb.* FROM tester@localhost;", 741 Expected: []sql.Row{{types.NewOkResult(0)}}, 742 }, 743 { 744 User: "tester", 745 Host: "localhost", 746 Query: "alter table test drop check chk1;", 747 ExpectedErr: sql.ErrPrivilegeCheckFailed, 748 }, 749 { 750 User: "root", 751 Host: "localhost", 752 Query: "GRANT alter ON mydb.* TO tester@localhost;", 753 Expected: []sql.Row{{types.NewOkResult(0)}}, 754 }, 755 { 756 User: "tester", 757 Host: "localhost", 758 Query: "alter table test drop check chk1;", 759 Expected: []sql.Row{}, 760 }, 761 { 762 User: "tester", 763 Host: "localhost", 764 Query: "show create table test;", 765 Expected: []sql.Row{ 766 {"test", "CREATE TABLE `test` (\n" + 767 " `pk` bigint NOT NULL,\n" + 768 " `a` int,\n" + 769 " PRIMARY KEY (`pk`)\n" + 770 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 771 }, 772 }, 773 { 774 User: "tester", 775 Host: "localhost", 776 Query: "alter table test add constraint chk1 CHECK (a < 10);", 777 Expected: []sql.Row{{types.NewOkResult(0)}}, 778 }, 779 { 780 User: "root", 781 Host: "localhost", 782 Query: "REVOKE alter ON mydb.* FROM tester@localhost;", 783 Expected: []sql.Row{{types.NewOkResult(0)}}, 784 }, 785 { 786 User: "tester", 787 Host: "localhost", 788 Query: "alter table test drop constraint chk1;", 789 ExpectedErr: sql.ErrPrivilegeCheckFailed, 790 }, 791 { 792 User: "root", 793 Host: "localhost", 794 Query: "GRANT alter ON mydb.* TO tester@localhost;", 795 Expected: []sql.Row{{types.NewOkResult(0)}}, 796 }, 797 { 798 User: "tester", 799 Host: "localhost", 800 Query: "alter table test drop constraint chk1;", 801 Expected: []sql.Row{}, 802 }, 803 { 804 User: "tester", 805 Host: "localhost", 806 Query: "show create table test;", 807 Expected: []sql.Row{ 808 {"test", "CREATE TABLE `test` (\n" + 809 " `pk` bigint NOT NULL,\n" + 810 " `a` int,\n" + 811 " PRIMARY KEY (`pk`)\n" + 812 ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}, 813 }, 814 }, 815 }, 816 }, 817 { 818 Name: "Basic revoke SELECT privilege", 819 SetUpScript: []string{ 820 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 821 "INSERT INTO test VALUES (1), (2), (3);", 822 "call dolt_commit('-Am', 'first commit');", 823 "call dolt_branch('b1')", 824 "use mydb/b1;", 825 "CREATE USER tester@localhost;", 826 "GRANT SELECT ON mydb.* TO tester@localhost;", 827 }, 828 Assertions: []queries.UserPrivilegeTestAssertion{ 829 { 830 User: "tester", 831 Host: "localhost", 832 Query: "SELECT * FROM test;", 833 Expected: []sql.Row{{1}, {2}, {3}}, 834 }, 835 { 836 User: "root", 837 Host: "localhost", 838 Query: "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';", 839 Expected: []sql.Row{{"tester", "localhost", "N"}}, 840 }, 841 { 842 User: "root", 843 Host: "localhost", 844 Query: "REVOKE SELECT ON mydb.* FROM tester@localhost;", 845 Expected: []sql.Row{{types.NewOkResult(0)}}, 846 }, 847 { 848 User: "tester", 849 Host: "localhost", 850 Query: "SELECT * FROM test;", 851 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 852 }, 853 { 854 User: "root", 855 Host: "localhost", 856 Query: "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';", 857 Expected: []sql.Row{{"tester", "localhost", "N"}}, 858 }, 859 }, 860 }, 861 { 862 Name: "Grant Role with SELECT Privilege", 863 SetUpScript: []string{ 864 "SET @@GLOBAL.activate_all_roles_on_login = true;", 865 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 866 "INSERT INTO test VALUES (1), (2), (3);", 867 "call dolt_commit('-Am', 'first commit');", 868 "call dolt_branch('b1')", 869 "use mydb/b1;", 870 "CREATE USER tester@localhost;", 871 "CREATE ROLE test_role;", 872 "GRANT SELECT ON mydb.* TO test_role;", 873 }, 874 Assertions: []queries.UserPrivilegeTestAssertion{ 875 { 876 User: "tester", 877 Host: "localhost", 878 Query: "SELECT * FROM test;", 879 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 880 }, 881 { 882 User: "root", 883 Host: "localhost", 884 Query: "SELECT COUNT(*) FROM mysql.role_edges;", 885 Expected: []sql.Row{{0}}, 886 }, 887 { 888 User: "root", 889 Host: "localhost", 890 Query: "GRANT test_role TO tester@localhost;", 891 Expected: []sql.Row{{types.NewOkResult(0)}}, 892 }, 893 { 894 User: "root", 895 Host: "localhost", 896 Query: "SELECT * FROM mysql.role_edges;", 897 Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}}, 898 }, 899 { 900 User: "tester", 901 Host: "localhost", 902 Query: "SELECT * FROM test;", 903 Expected: []sql.Row{{1}, {2}, {3}}, 904 }, 905 { 906 User: "root", 907 Host: "localhost", 908 Query: "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';", 909 Expected: []sql.Row{{"tester", "localhost", "N"}}, 910 }, 911 }, 912 }, 913 { 914 Name: "Revoke role currently granted to a user", 915 SetUpScript: []string{ 916 "SET @@GLOBAL.activate_all_roles_on_login = true;", 917 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 918 "INSERT INTO test VALUES (1), (2), (3);", 919 "call dolt_commit('-Am', 'first commit');", 920 "call dolt_branch('b1')", 921 "use mydb/b1;", 922 "CREATE USER tester@localhost;", 923 "CREATE ROLE test_role;", 924 "GRANT SELECT ON mydb.* TO test_role;", 925 "GRANT test_role TO tester@localhost;", 926 }, 927 Assertions: []queries.UserPrivilegeTestAssertion{ 928 { 929 User: "tester", 930 Host: "localhost", 931 Query: "SELECT * FROM test;", 932 Expected: []sql.Row{{1}, {2}, {3}}, 933 }, 934 { 935 User: "root", 936 Host: "localhost", 937 Query: "SELECT * FROM mysql.role_edges;", 938 Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}}, 939 }, 940 { 941 User: "root", 942 Host: "localhost", 943 Query: "REVOKE test_role FROM tester@localhost;", 944 Expected: []sql.Row{{types.NewOkResult(0)}}, 945 }, 946 { 947 User: "tester", 948 Host: "localhost", 949 Query: "SELECT * FROM test;", 950 ExpectedErr: sql.ErrDatabaseAccessDeniedForUser, 951 }, 952 { 953 User: "root", 954 Host: "localhost", 955 Query: "SELECT COUNT(*) FROM mysql.role_edges;", 956 Expected: []sql.Row{{0}}, 957 }, 958 { 959 User: "root", 960 Host: "localhost", 961 Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';", 962 Expected: []sql.Row{{1}}, 963 }, 964 { 965 User: "root", 966 Host: "localhost", 967 Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';", 968 Expected: []sql.Row{{1}}, 969 }, 970 }, 971 }, 972 } 973 974 func TestDoltOnlyRevisionDatabasePrivileges(t *testing.T) { 975 for _, script := range DoltOnlyRevisionDbPrivilegeTests { 976 harness := newDoltHarness(t) 977 harness.Setup(setup.MydbData, setup.MytableData) 978 t.Run(script.Name, func(t *testing.T) { 979 engine := mustNewEngine(t, harness) 980 defer engine.Close() 981 982 ctx := enginetest.NewContext(harness) 983 ctx.NewCtxWithClient(sql.Client{ 984 User: "root", 985 Address: "localhost", 986 }) 987 engine.EngineAnalyzer().Catalog.MySQLDb.AddRootAccount() 988 engine.EngineAnalyzer().Catalog.MySQLDb.SetPersister(&mysql_db.NoopPersister{}) 989 990 for _, statement := range script.SetUpScript { 991 enginetest.RunQueryWithContext(t, engine, harness, ctx, statement) 992 } 993 994 for _, assertion := range script.Assertions { 995 user := assertion.User 996 host := assertion.Host 997 if user == "" { 998 user = "root" 999 } 1000 if host == "" { 1001 host = "localhost" 1002 } 1003 ctx := enginetest.NewContextWithClient(harness, sql.Client{ 1004 User: user, 1005 Address: host, 1006 }) 1007 ctx.SetCurrentDatabase("mydb/b1") 1008 1009 if assertion.ExpectedErr != nil { 1010 t.Run(assertion.Query, func(t *testing.T) { 1011 enginetest.AssertErrWithCtx(t, engine, harness, ctx, assertion.Query, assertion.ExpectedErr) 1012 }) 1013 } else if assertion.ExpectedErrStr != "" { 1014 t.Run(assertion.Query, func(t *testing.T) { 1015 enginetest.AssertErrWithCtx(t, engine, harness, ctx, assertion.Query, nil, assertion.ExpectedErrStr) 1016 }) 1017 } else { 1018 t.Run(assertion.Query, func(t *testing.T) { 1019 enginetest.TestQueryWithContext(t, ctx, engine, harness, assertion.Query, assertion.Expected, nil, nil) 1020 }) 1021 } 1022 } 1023 }) 1024 } 1025 }