Skip to content

Commit

Permalink
Added roles, revoking, and dropping users and roles
Browse files Browse the repository at this point in the history
  • Loading branch information
Hydrocharged committed Jan 31, 2022
1 parent 8e12c85 commit 5c252c7
Show file tree
Hide file tree
Showing 17 changed files with 1,110 additions and 40 deletions.
337 changes: 337 additions & 0 deletions enginetest/priv_auth_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,343 @@ var UserPrivTests = []UserPrivilegeTest{
},
},
},
{
Name: "Basic revoke SELECT privilege",
SetUpScript: []string{
"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
"INSERT INTO test VALUES (1), (2), (3);",
"CREATE USER tester@localhost;",
"GRANT SELECT ON *.* TO tester@localhost;",
},
Assertions: []UserPrivilegeTestAssertion{
{
User: "tester",
Host: "localhost",
Query: "SELECT * FROM test;",
Expected: []sql.Row{{1}, {2}, {3}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';",
Expected: []sql.Row{{"tester", "localhost", "Y"}},
},
{
User: "root",
Host: "localhost",
Query: "REVOKE SELECT ON *.* FROM tester@localhost;",
Expected: []sql.Row{{sql.NewOkResult(0)}},
},
{
User: "tester",
Host: "localhost",
Query: "SELECT * FROM test;",
ExpectedErr: sql.ErrPrivilegeCheckFailed,
},
{
User: "root",
Host: "localhost",
Query: "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';",
Expected: []sql.Row{{"tester", "localhost", "N"}},
},
},
},
{
Name: "Basic revoke all global static privileges",
SetUpScript: []string{
"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
"INSERT INTO test VALUES (1), (2), (3);",
"CREATE USER tester@localhost;",
"GRANT ALL ON *.* TO tester@localhost;",
},
Assertions: []UserPrivilegeTestAssertion{
{
User: "tester",
Host: "localhost",
Query: "INSERT INTO test VALUES (4);",
Expected: []sql.Row{{sql.NewOkResult(1)}},
},
{
User: "tester",
Host: "localhost",
Query: "SELECT * FROM test;",
Expected: []sql.Row{{1}, {2}, {3}, {4}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT User, Host, Select_priv, Insert_priv FROM mysql.user WHERE User = 'tester';",
Expected: []sql.Row{{"tester", "localhost", "Y", "Y"}},
},
{
User: "root",
Host: "localhost",
Query: "REVOKE ALL ON *.* FROM tester@localhost;",
Expected: []sql.Row{{sql.NewOkResult(0)}},
},
{
User: "tester",
Host: "localhost",
Query: "SELECT * FROM test;",
ExpectedErr: sql.ErrPrivilegeCheckFailed,
},
{
User: "tester",
Host: "localhost",
Query: "INSERT INTO test VALUES (5);",
ExpectedErr: sql.ErrPrivilegeCheckFailed,
},
{
User: "root",
Host: "localhost",
Query: "SELECT User, Host, Select_priv, Insert_priv FROM mysql.user WHERE User = 'tester';",
Expected: []sql.Row{{"tester", "localhost", "N", "N"}},
},
},
},
{
Name: "Basic role creation",
SetUpScript: []string{
"CREATE ROLE test_role;",
},
Assertions: []UserPrivilegeTestAssertion{
{
User: "root",
Host: "localhost",
Query: "SELECT User, Host, account_locked FROM mysql.user WHERE User = 'test_role';",
Expected: []sql.Row{{"test_role", "%", "Y"}},
},
},
},
{
Name: "Grant Role with SELECT Privilege",
SetUpScript: []string{
"SET @@GLOBAL.activate_all_roles_on_login = true;",
"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
"INSERT INTO test VALUES (1), (2), (3);",
"CREATE USER tester@localhost;",
"CREATE ROLE test_role;",
"GRANT SELECT ON *.* TO test_role;",
},
Assertions: []UserPrivilegeTestAssertion{
{
User: "tester",
Host: "localhost",
Query: "SELECT * FROM test;",
ExpectedErr: sql.ErrPrivilegeCheckFailed,
},
{
User: "root",
Host: "localhost",
Query: "SELECT COUNT(*) FROM mysql.role_edges;",
Expected: []sql.Row{{0}},
},
{
User: "root",
Host: "localhost",
Query: "GRANT test_role TO tester@localhost;",
Expected: []sql.Row{{sql.NewOkResult(0)}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT * FROM mysql.role_edges;",
Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}},
},
{
User: "tester",
Host: "localhost",
Query: "SELECT * FROM test;",
Expected: []sql.Row{{1}, {2}, {3}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';",
Expected: []sql.Row{{"tester", "localhost", "N"}},
},
},
},
{
Name: "Revoke role currently granted to a user",
SetUpScript: []string{
"SET @@GLOBAL.activate_all_roles_on_login = true;",
"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
"INSERT INTO test VALUES (1), (2), (3);",
"CREATE USER tester@localhost;",
"CREATE ROLE test_role;",
"GRANT SELECT ON *.* TO test_role;",
"GRANT test_role TO tester@localhost;",
},
Assertions: []UserPrivilegeTestAssertion{
{
User: "tester",
Host: "localhost",
Query: "SELECT * FROM test;",
Expected: []sql.Row{{1}, {2}, {3}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT * FROM mysql.role_edges;",
Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}},
},
{
User: "root",
Host: "localhost",
Query: "REVOKE test_role FROM tester@localhost;",
Expected: []sql.Row{{sql.NewOkResult(0)}},
},
{
User: "tester",
Host: "localhost",
Query: "SELECT * FROM test;",
ExpectedErr: sql.ErrPrivilegeCheckFailed,
},
{
User: "root",
Host: "localhost",
Query: "SELECT COUNT(*) FROM mysql.role_edges;",
Expected: []sql.Row{{0}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';",
Expected: []sql.Row{{1}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';",
Expected: []sql.Row{{1}},
},
},
},
{
Name: "Drop role currently granted to a user",
SetUpScript: []string{
"SET @@GLOBAL.activate_all_roles_on_login = true;",
"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
"INSERT INTO test VALUES (1), (2), (3);",
"CREATE USER tester@localhost;",
"CREATE ROLE test_role;",
"GRANT SELECT ON *.* TO test_role;",
"GRANT test_role TO tester@localhost;",
},
Assertions: []UserPrivilegeTestAssertion{
{
User: "tester",
Host: "localhost",
Query: "SELECT * FROM test;",
Expected: []sql.Row{{1}, {2}, {3}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT * FROM mysql.role_edges;",
Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}},
},
{
User: "root",
Host: "localhost",
Query: "DROP ROLE test_role;",
Expected: []sql.Row{{sql.NewOkResult(0)}},
},
{
User: "tester",
Host: "localhost",
Query: "SELECT * FROM test;",
ExpectedErr: sql.ErrPrivilegeCheckFailed,
},
{
User: "root",
Host: "localhost",
Query: "SELECT COUNT(*) FROM mysql.role_edges;",
Expected: []sql.Row{{0}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';",
Expected: []sql.Row{{0}},
},
{ // Ensure nothing wonky happened like the user was deleted as well
User: "root",
Host: "localhost",
Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';",
Expected: []sql.Row{{1}},
},
{
User: "root",
Host: "localhost",
Query: "DROP ROLE test_role;",
ExpectedErr: sql.ErrRoleDeletionFailure,
},
{
User: "root",
Host: "localhost",
Query: "DROP ROLE IF EXISTS test_role;",
Expected: []sql.Row{{sql.NewOkResult(0)}},
},
},
},
{
Name: "Drop user with role currently granted",
SetUpScript: []string{
"SET @@GLOBAL.activate_all_roles_on_login = true;",
"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
"INSERT INTO test VALUES (1), (2), (3);",
"CREATE USER tester@localhost;",
"CREATE ROLE test_role;",
"GRANT SELECT ON *.* TO test_role;",
"GRANT test_role TO tester@localhost;",
},
Assertions: []UserPrivilegeTestAssertion{
{
User: "root",
Host: "localhost",
Query: "SELECT * FROM mysql.role_edges;",
Expected: []sql.Row{{"%", "test_role", "localhost", "tester", "N"}},
},
{
User: "root",
Host: "localhost",
Query: "DROP USER tester@localhost;",
Expected: []sql.Row{{sql.NewOkResult(0)}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT COUNT(*) FROM mysql.role_edges;",
Expected: []sql.Row{{0}},
},
{
User: "root",
Host: "localhost",
Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';",
Expected: []sql.Row{{0}},
},
{ // Ensure nothing wonky happened like the role was deleted as well
User: "root",
Host: "localhost",
Query: "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';",
Expected: []sql.Row{{1}},
},
{
User: "root",
Host: "localhost",
Query: "DROP USER tester@localhost;",
ExpectedErr: sql.ErrUserDeletionFailure,
},
{
User: "root",
Host: "localhost",
Query: "DROP USER IF EXISTS tester@localhost;",
Expected: []sql.Row{{sql.NewOkResult(0)}},
},
},
},
}

// ServerAuthTests test the server authentication system. These tests always have the root account available, and the
Expand Down
15 changes: 7 additions & 8 deletions sql/analyzer/privileges.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,33 +35,32 @@ func checkPrivileges(ctx *sql.Context, a *Analyzer, n sql.Node, scope *Scope) (s
return n, nil
}

client := ctx.Session.Client()
user := a.Catalog.GrantTables.GetUser(client.User, client.Address, false)
user, privSet := a.Catalog.GrantTables.GetUserPrivileges(ctx)
if user == nil {
return nil, mysql.NewSQLError(mysql.ERAccessDeniedError, mysql.SSAccessDeniedError, "Access denied for user '%v'", client.User)
return nil, mysql.NewSQLError(mysql.ERAccessDeniedError, mysql.SSAccessDeniedError, "Access denied for user '%v'", ctx.Session.Client().User)
}

switch n := n.(type) {
case *plan.InsertInto:
if n.IsReplace {
if !user.PrivilegeSet.Has(grant_tables.PrivilegeType_Insert, grant_tables.PrivilegeType_Delete) {
if !privSet.Has(grant_tables.PrivilegeType_Insert, grant_tables.PrivilegeType_Delete) {
return nil, sql.ErrPrivilegeCheckFailed.New("REPLACE", user.UserHostToString("'", `\'`), getTableName(n.Destination))
}
} else if !user.PrivilegeSet.Has(grant_tables.PrivilegeType_Insert) {
} else if !privSet.Has(grant_tables.PrivilegeType_Insert) {
return nil, sql.ErrPrivilegeCheckFailed.New("INSERT", user.UserHostToString("'", `\'`), getTableName(n.Destination))
}
case *plan.Update:
if !user.PrivilegeSet.Has(grant_tables.PrivilegeType_Update) {
if !privSet.Has(grant_tables.PrivilegeType_Update) {
return nil, sql.ErrPrivilegeCheckFailed.New("UPDATE", user.UserHostToString("'", `\'`), getTableName(n.Child))
}
case *plan.DeleteFrom:
if !user.PrivilegeSet.Has(grant_tables.PrivilegeType_Delete) {
if !privSet.Has(grant_tables.PrivilegeType_Delete) {
return nil, sql.ErrPrivilegeCheckFailed.New("DELETE", user.UserHostToString("'", `\'`), getTableName(n.Child))
}
case *plan.Project:
//TODO: a better way to do this would be to inspect the children of some nodes, such as filter nodes, and
//recursively inspect their children until we get to a more well-defined node.
if !user.PrivilegeSet.Has(grant_tables.PrivilegeType_Select) {
if !privSet.Has(grant_tables.PrivilegeType_Select) {
return nil, sql.ErrPrivilegeCheckFailed.New("SELECT", user.UserHostToString("'", `\'`), getTableName(n.Child))
}
default:
Expand Down
Loading

0 comments on commit 5c252c7

Please sign in to comment.