В этой статье речь пойдет о том как дать пользователям доступ на выполнение процедур, которые для своей работы требуют мощных серверных разрешений, не давая при этом этих разрешений пользователям. Предположим, что мы разрабатываем базу данных, в которой высокоприоритетные соединения могут блокироваться неким низкоприоритетным процессом. И в таких ситуациях требуется делать kill для этого низкоприоритетного процесса, то есть отключать мешающее соединение. Предположим задача на отключение соединений возложена на младшего разработчика. Причем по реглементу ему нельзя предоставлять ни прав администратора, ни доступа на отключение всех соединений. Для сотрудника созданы такие аутентификационные данные:
Напишем для решения задачи такую процедуру:
В процедуре происходит отключение соединений, которые кого-либо блокируют и при этом работают на определенном хосте. Это и есть наш критерий низко-приоритетного соединения.
Смоделируем ситуацию когда происходит блокирование. Создим таблицу:
create table dbo.Data ( i int )
На компьютере с именем EDYNAK запустим такой код:
Другое соединение пытается прочитать данные и становится в очередь:
Теперь попробуем запустить процедуру от имени testUser:
Происходит ошибка с таким описанием:
Как видно предоставление доступа через grant не обеспечивает наличия прав на kill через процедуру. Что же делать? Можно включить логин testUser в роль setupadmin, но тогда он сможет отлючать любые соединения. Помогут сертификаты!
Создадим в базе данных master самоподписанный сертификат:
Мы задали защиту сертификата через пароль, указали сроки его действия (это опционально), задали описание. Теперь на основе созданного сертификата создадим логин:
create login KillWongSessLog from certificate KillWrongSessCert
Под данным логином никто не сможет подключиться к серверу, поэтому ему можно спокойно дать доступ на kill любых соединений:
alter server role processadmin add member KillWongSessLog
Пока мы работали с базой данных master. Чтобы перейти к нашей базе Data требуется создать резервеую копию сертификата:
В этом коде мы задали место хранения резервной копии сертификата, указали для дешифровки тот же пароль, который используется для защиты сертификата, а также задали пароль для хранения приватного ключа. Восстановим сохраненную копию в базе Data:
Теперь осталось подписать хранимую процедуру созданным сертификатом:
add signature to dbo.KillWrongSessions by certificate KillWrongSessCert with password = N'$%#$T$#TE'
Здесь также указывается пароль, защищающий сертификат.
Запускаем код:
Код отработал без ошибок! По аналогии можно создавать процедуры, которые делают, например, бэкапирование баз данных, манипуляции с файлами, связанными серверами или что-нибудь еще. И при этом, через подписание процедур сертификатами, давать доступ на их запуск пользователям, не давая последним никаких прав. Одну и ту же процедуру можно подписать любым числом сертификатов, что позволяет выполнять в одной процедуре несколько действий.
create
login testUser with
password = 'testdata', check_policy = off, default_database = Data
create user testUser from login testUser with default_schema = dboНапишем для решения задачи такую процедуру:
use
Data
go
if
sessionproperty ( N'quoted_identifier'
) = 0
set quoted_identifier on
go
if
sessionproperty ( N'ansi_nulls' ) = 0
set ansi_nulls on
go
create
proc dbo.KillWrongSessions
as
begin
set nocount, xact_abort on
declare
@sess int, @sql
nvarchar ( max )
declare
cur cursor local
static forward_only
for
select
block.session_id
from
sys.dm_exec_requests
sess
inner join
sys.dm_exec_sessions
block on sess.blocking_session_id
= block.session_id
where
sess.blocking_session_id <> 0 and block.[host_name] = 'EDYNAK'
open cur
fetch next from cur into @sess
while @@fetch_status = 0
begin
set
@sql = 'kill ' + cast ( @sess as nvarchar ( 100 ) )
--print
@sql
exec
sp_executesql @sql
fetch
next from cur into @sess
end
close cur
deallocate
cur
end
go
grant
exec on object::dbo.KillWrongSessions to
testUser
use master
grant view server state to testUserВ процедуре происходит отключение соединений, которые кого-либо блокируют и при этом работают на определенном хосте. Это и есть наш критерий низко-приоритетного соединения.
Смоделируем ситуацию когда происходит блокирование. Создим таблицу:
create table dbo.Data ( i int )
На компьютере с именем EDYNAK запустим такой код:
begin
tran
insert
into dbo.Data ( i )
select 1Другое соединение пытается прочитать данные и становится в очередь:
select *
from dbo.DataТеперь попробуем запустить процедуру от имени testUser:
exec
as login = 'testUser'
exec dbo.KillWrongSessions
go
revertПроисходит ошибка с таким описанием:
Msg 6102,
Level 14, State 1, Line 77
User does not have
permission to use the KILL statement.Как видно предоставление доступа через grant не обеспечивает наличия прав на kill через процедуру. Что же делать? Можно включить логин testUser в роль setupadmin, но тогда он сможет отлючать любые соединения. Помогут сертификаты!
Создадим в базе данных master самоподписанный сертификат:
use
master
create
certificate KillWrongSessCert
encryption
by password = N'$%#$T$#TE'
with subject = N'Сертификат для отключения
только некоторых соединений.',
start_date = '2013-12-31',
expiry_date
= '2015-12-31'Мы задали защиту сертификата через пароль, указали сроки его действия (это опционально), задали описание. Теперь на основе созданного сертификата создадим логин:
create login KillWongSessLog from certificate KillWrongSessCert
Под данным логином никто не сможет подключиться к серверу, поэтому ему можно спокойно дать доступ на kill любых соединений:
alter server role processadmin add member KillWongSessLog
Пока мы работали с базой данных master. Чтобы перейти к нашей базе Data требуется создать резервеую копию сертификата:
backup
certificate KillWrongSessCert to file = 'C:\Users\Edynak\Desktop\KillWrongSessCert.cer'
with private key
(
file
= 'C:\Users\Edynak\Desktop\KillWrongSessCert.pvk',
encryption
by password = N'#$#D',
decryption
by password = N'$%#$T$#TE'
)В этом коде мы задали место хранения резервной копии сертификата, указали для дешифровки тот же пароль, который используется для защиты сертификата, а также задали пароль для хранения приватного ключа. Восстановим сохраненную копию в базе Data:
use
Data
create
certificate KillWrongSessCert
from file = 'C:\Users\Edynak\Desktop\KillWrongSessCert.cer'
with private key
(
file
= 'C:\Users\Edynak\Desktop\KillWrongSessCert.pvk',
encryption
by password = N'$%#$T$#TE',
decryption
by password = N'#$#D'
)Теперь осталось подписать хранимую процедуру созданным сертификатом:
add signature to dbo.KillWrongSessions by certificate KillWrongSessCert with password = N'$%#$T$#TE'
Здесь также указывается пароль, защищающий сертификат.
Запускаем код:
exec as login = 'testUser'
exec dbo.KillWrongSessions
go
revertКод отработал без ошибок! По аналогии можно создавать процедуры, которые делают, например, бэкапирование баз данных, манипуляции с файлами, связанными серверами или что-нибудь еще. И при этом, через подписание процедур сертификатами, давать доступ на их запуск пользователям, не давая последним никаких прав. Одну и ту же процедуру можно подписать любым числом сертификатов, что позволяет выполнять в одной процедуре несколько действий.
Комментариев нет:
Отправить комментарий