Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added privilege checks for every currently supported statement #797

Merged
merged 1 commit into from
Feb 15, 2022

Conversation

Hydrocharged
Copy link
Contributor

This adds privileges for every supported statement.

@Hydrocharged
Copy link
Contributor Author

Hydrocharged commented Feb 14, 2022

No explicit tests because I didn't have the time (the existing tests do some testing but it's not exhaustive at all), and also I can't verify that every statement checks for the correct privileges as I didn't have time. Most statements should have the correct privileges though.

Copy link
Member

@zachmu zachmu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first I was a bit turned off by the addition of a new interface method to Node, but I have to admit it makes a lot of sense. Nice work.

Only comment here is that some of these implementations seem like they should really be checking permissions on child nodes, but aren't because the analyzer does for them. 1) Make sure there are permissions tests of the correct behavior, 2) probably do the check anyway.

// WithChildren implements the Node interface.
func (p *CreateForeignKey) WithChildren(children ...sql.Node) (sql.Node, error) {
return NillaryWithChildren(p, children...)
}

// CheckPrivileges implements the interface sql.Node.
func (p *CreateForeignKey) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool {
return opChecker.UserHasPrivileges(ctx,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs ALTER too right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MySQL is not consistent on what privileges are needed at times. Take CREATE USER, which can handle creating a user, renaming them, and dropping them. And, for some reason, specifically the REVOKE ALL PRIVILEGES statement, but no other REVOKE statement.

sql/plan/create_role.go Show resolved Hide resolved
sql/plan/drop_role.go Show resolved Hide resolved
sql/plan/drop_user.go Show resolved Hide resolved
@@ -74,6 +74,12 @@ func (sc ShowCreateTable) WithChildren(children ...sql.Node) (sql.Node, error) {
return &sc, nil
}

// CheckPrivileges implements the interface sql.Node.
func (sc *ShowCreateTable) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool {
// The table won't be visible during the resolution step if the user doesn't have the correct privileges
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure there are tests of this behavior

@@ -187,6 +187,12 @@ func (s ShowColumns) WithChildren(children ...sql.Node) (sql.Node, error) {
return &s, nil
}

// CheckPrivileges implements the interface sql.Node.
func (s *ShowColumns) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool {
// The table won't be visible during the resolution step if the user doesn't have the correct privileges
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, tests

It also seems strange that we wouldn't just call Child.CheckPrivileges, we have the table in the node

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So failing CheckPrivileges results in an error being thrown. In some of these statements, we don't want to error, we'll just show nothing, so we let those other checks handle those parts. I can't quite verify that for this particular statement (most of these SHOW statements were done last), but that's the general idea for most of these SHOW statements that just return true.

// CheckPrivileges implements the interface sql.Node.
func (p *Truncate) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool {
return opChecker.UserHasPrivileges(ctx,
sql.NewPrivilegedOperation(p.db, getTableName(p.Child), "", sql.PrivilegeType_Drop))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't just DELETE?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like it should be, but perhaps it's closer to a DROP TABLE internally so they rely on DROP instead of DELETE.

@Hydrocharged Hydrocharged merged commit c484f95 into main Feb 15, 2022
@Hydrocharged Hydrocharged deleted the daylon/users-10 branch February 15, 2022 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants