Fix TRIGGER checks for MySQL

This ensures we can check if the user has TRIGGER permissions without
querying restricted tables. Thanks to Steve Norman
(https://gitlab.com/stevenorman) for helping out with this merge
request.

Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/38372
This commit is contained in:
Yorick Peterse 2017-11-06 18:50:38 +01:00
parent c71cf908cd
commit 60526a5291
No known key found for this signature in database
GPG Key ID: EDD30D2BEB691AC9
3 changed files with 29 additions and 28 deletions

View File

@ -0,0 +1,5 @@
---
title: Fix TRIGGER checks for MySQL
merge_request:
author:
type: fixed

View File

@ -6,28 +6,36 @@ module Gitlab
if Database.postgresql?
'information_schema.role_table_grants'
else
'mysql.user'
'information_schema.schema_privileges'
end
def self.scope_to_current_user
if Database.postgresql?
where('grantee = user')
else
where("CONCAT(User, '@', Host) = current_user()")
end
end
# Returns true if the current user can create and execute triggers on the
# given table.
def self.create_and_execute_trigger?(table)
priv =
if Database.postgresql?
where(privilege_type: 'TRIGGER', table_name: table)
.where('grantee = user')
else
where(Trigger_priv: 'Y')
queries = [
Grant.select(1)
.from('information_schema.user_privileges')
.where("PRIVILEGE_TYPE = 'SUPER'")
.where("GRANTEE = CONCAT('\\'', REPLACE(CURRENT_USER(), '@', '\\'@\\''), '\\'')"),
Grant.select(1)
.from('information_schema.schema_privileges')
.where("PRIVILEGE_TYPE = 'TRIGGER'")
.where('TABLE_SCHEMA = ?', Gitlab::Database.database_name)
.where("GRANTEE = CONCAT('\\'', REPLACE(CURRENT_USER(), '@', '\\'@\\''), '\\'')")
]
union = SQL::Union.new(queries).to_sql
Grant.from("(#{union}) privs")
end
priv.scope_to_current_user.any?
priv.any?
end
end
end

View File

@ -1,16 +1,6 @@
require 'spec_helper'
describe Gitlab::Database::Grant do
describe '.scope_to_current_user' do
it 'scopes the relation to the current user' do
user = Gitlab::Database.username
column = Gitlab::Database.postgresql? ? :grantee : :User
names = described_class.scope_to_current_user.pluck(column).uniq
expect(names).to eq([user])
end
end
describe '.create_and_execute_trigger' do
it 'returns true when the user can create and execute a trigger' do
# We assume the DB/user is set up correctly so that triggers can be
@ -18,13 +8,11 @@ describe Gitlab::Database::Grant do
expect(described_class.create_and_execute_trigger?('users')).to eq(true)
end
it 'returns false when the user can not create and/or execute a trigger' do
allow(described_class).to receive(:scope_to_current_user)
.and_return(described_class.none)
result = described_class.create_and_execute_trigger?('kittens')
expect(result).to eq(false)
it 'returns false when the user can not create and/or execute a trigger', :postgresql do
# In case of MySQL the user may have SUPER permissions, making it
# impossible to have `false` returned when running tests; hence we only
# run these tests on PostgreSQL.
expect(described_class.create_and_execute_trigger?('foo')).to eq(false)
end
end
end