Commit 667be38d authored by Rémy Coutable's avatar Rémy Coutable Committed by Stan Hu

Merge branch 'fix-mysql-grant-check' into 'master'

Fix TRIGGER checks for MySQL

Closes #38372

See merge request gitlab-org/gitlab-ce!15226
parent 49a2f7e0
---
title: Fix TRIGGER checks for MySQL
merge_request:
author:
type: fixed
...@@ -6,28 +6,36 @@ module Gitlab ...@@ -6,28 +6,36 @@ module Gitlab
if Database.postgresql? if Database.postgresql?
'information_schema.role_table_grants' 'information_schema.role_table_grants'
else else
'mysql.user' 'information_schema.schema_privileges'
end 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 # Returns true if the current user can create and execute triggers on the
# given table. # given table.
def self.create_and_execute_trigger?(table) def self.create_and_execute_trigger?(table)
priv = priv =
if Database.postgresql? if Database.postgresql?
where(privilege_type: 'TRIGGER', table_name: table) where(privilege_type: 'TRIGGER', table_name: table)
.where('grantee = user')
else 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 end
priv.scope_to_current_user.any? priv.any?
end end
end end
end end
......
require 'spec_helper' require 'spec_helper'
describe Gitlab::Database::Grant do 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 describe '.create_and_execute_trigger' do
it 'returns true when the user can create and execute a 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 # We assume the DB/user is set up correctly so that triggers can be
...@@ -18,13 +8,11 @@ describe Gitlab::Database::Grant do ...@@ -18,13 +8,11 @@ describe Gitlab::Database::Grant do
expect(described_class.create_and_execute_trigger?('users')).to eq(true) expect(described_class.create_and_execute_trigger?('users')).to eq(true)
end end
it 'returns false when the user can not create and/or execute a trigger' do it 'returns false when the user can not create and/or execute a trigger', :postgresql do
allow(described_class).to receive(:scope_to_current_user) # In case of MySQL the user may have SUPER permissions, making it
.and_return(described_class.none) # impossible to have `false` returned when running tests; hence we only
# run these tests on PostgreSQL.
result = described_class.create_and_execute_trigger?('kittens') expect(described_class.create_and_execute_trigger?('foo')).to eq(false)
expect(result).to eq(false)
end end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment