Advertisement
PavloSerg

ProtectDB_Laba4(5)_DDL_Trigger

Nov 30th, 2023 (edited)
1,858
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
T-SQL 12.19 KB | None | 0 0
  1. --Задание 1
  2.  
  3. -- Создать роль базы данных “DevUserRole”.Эта роль должна быть членом
  4. -- ролей базы данных db_datareader и db_datawriter.Напишите скрипт для
  5. -- предоставления прав DevUserRole на выполнение всех существующих в
  6. -- заданной БД хранимых процедур.
  7. -- Реализуйте триггер DDL для того чтобы автоматически выдавать права роли
  8. -- DevUserRole на выполнение всех вновь создаваемых в схеме “dbo” хранимых
  9. -- процедур.
  10.  
  11.  
  12. --1) Создать роль базы данных “DevUserRole”.Эта роль должна быть членом
  13. -- ролей базы данных db_datareader и db_datawriter.
  14. DROP ROLE IF EXISTS DevUserRole
  15. go
  16. CREATE ROLE DevUserRole
  17. go
  18. alter role db_datareader add member DevUserRole
  19. alter role db_datawriter add member DevUserRole
  20. go
  21.  
  22.  
  23. --2) Напишите скрипт для
  24. -- предоставления прав DevUserRole на выполнение всех существующих в
  25. -- заданной БД хранимых процедур.
  26.  
  27. --2.1) Для начала создадим фиктивные функции для теста
  28. create procedure Test1 as
  29. begin
  30.     print 1
  31. end
  32.  
  33. create procedure Test2 as
  34. begin
  35.     print 2
  36. end
  37.  
  38.  
  39. --2.2) Пишем скрипт для
  40. -- предоставления прав DevUserRole на выполнение всех существующих в
  41. -- заданной БД хранимых процедур.
  42. create or alter procedure GiveExecuteToAllExistsProcedures as
  43. begin
  44.     declare @currentSchemaAndProcNames nvarchar(200);
  45.     declare namesCursor cursor for
  46.         select sys.schemas.name + '.' + sys.procedures.name as schemaAndProcNames
  47.         from sys.procedures
  48.         join sys.schemas on sys.procedures.schema_id = sys.schemas.schema_id
  49.     open namesCursor;
  50.  
  51.     fetch next from namesCursor into @currentSchemaAndProcNames
  52.     while @@fetch_status=0
  53.     begin
  54.         declare @sqlCommand nvarchar(200) = 'grant execute on '+@currentSchemaAndProcNames+' to DevUserRole'
  55.         exec sp_executesql @sqlCommand
  56.         print(@sqlCommand)
  57.  
  58.         fetch next from namesCursor into @currentSchemaAndProcNames
  59.     end
  60.     close namesCursor;
  61.     deallocate namesCursor;
  62. end
  63.  
  64. execute GiveExecuteToAllExistsProcedures
  65.  
  66. --2.3) Тестим
  67. drop user if exists TestDevUserRoleUser
  68. create user TestDevUserRoleUser without login
  69. alter role DevUserRole add member TestDevUserRoleUser
  70.  
  71. execute as user = 'TestDevUserRoleUser'
  72. execute Test1
  73. go
  74. execute Test2
  75. go
  76. print N'Есть права и на GiveExecuteToAllExistsProcedures, но нет прав на выдачу прав -> выкинет ошибку'
  77. go
  78. execute GiveExecuteToAllExistsProcedures
  79. revert
  80. go
  81.  
  82. --3) Реализуйте триггер DDL для того чтобы автоматически выдавать права роли
  83. -- DevUserRole на выполнение всех вновь создаваемых в схеме “dbo” хранимых
  84. -- процедур.
  85.  
  86. --3.1) Пишем тригер
  87. CREATE OR ALTER TRIGGER NewUserAdditionTrigger
  88.     ON DATABASE
  89.     after CREATE_PROCEDURE
  90.     AS
  91. BEGIN
  92.     DECLARE @schemaName NVARCHAR(200) = EVENTDATA()
  93.         .value('(/EVENT_INSTANCE/SchemaName)[1]', 'nvarchar(256)')
  94.     if @schemaName != 'dbo'
  95.         return
  96.     DECLARE @procName NVARCHAR(200) = EVENTDATA()
  97.         .value('(/EVENT_INSTANCE/ObjectName)[1]', 'nvarchar(256)')
  98.     declare @currentSchemaAndProcNames NVARCHAR(400) = @schemaName + '.' + @procName
  99.     declare @sqlCommand nvarchar(200) = 'grant execute on '+@currentSchemaAndProcNames+' to DevUserRole'
  100.     exec sp_executesql @sqlCommand
  101.     print(@sqlCommand)
  102. END;
  103.  
  104. --3.2) Создаем тестовую таблицу, ручками права не выдаем!
  105. drop procedure if exists Test3
  106. go
  107. create procedure Test3 as
  108. begin
  109.     print 3
  110. end
  111. go
  112.  
  113. --3.3) Тестим
  114. execute as user = 'TestDevUserRoleUser'
  115. execute Test3
  116. revert
  117.  
  118.  
  119.  
  120. ------------------------------------------------------------------------------------------------
  121. ------------------------------------------------------------------------------------------------
  122. --Задание 2
  123.  
  124. --Реализовать аудит действий пользователя TestAdmin.
  125. --Пользователю должно быть разрешено подключение к DBServerv только во
  126. --время учебных пар по нашему курсу и только с компьютеров в 403 ауд. Все
  127. --неудачные попытки входа фиксировать в таблице LogAuditTestAdmin.
  128.  
  129. --1) Создадим пользователя и выдадим права
  130. --DROP LOGIN TestAdmin
  131. CREATE LOGIN TestAdmin WITH PASSWORD = 'TestAdmin';
  132. go
  133. --DROP USER TestAdmin
  134. CREATE USER TestAdmin FOR LOGIN TestAdmin;
  135. go
  136. alter role db_datareader add member TestAdmin
  137. alter role db_datawriter add member TestAdmin
  138. go
  139.  
  140. --2) Создадим таблицы
  141. --2.1) Таблицу расписания пар (разрешенных периодов)
  142. create table AllowedPeriods(
  143.     start datetime,
  144.     [end] datetime,
  145.     note nvarchar(255)
  146. )
  147. insert into AllowedPeriods
  148. values ('2023-12-06 10:45', '2023-12-06 12:20', N'Среда, числ, 2 пара'),
  149.        ('2023-12-06 13:20', '2023-12-06 14:55', N'Среда, числ, 3 пара'),--:00.000
  150.        ('2023-12-13 13:20', '2023-12-13 14:55', N'Среда, знам, 3 пара')
  151. --Сохраняем дату начала и конца первой пары чтобы не придумывать сложных
  152. --систем вычисления четности недели(числитель, знаменатель)
  153.  
  154. --2.2) Таблицу разрешенных компьютеров
  155. --Тут на самом деле есть несколько путей
  156. --Можно, к примеру, по айпи адресу попробовать анализировать маску подсети
  157. --или еще что-нибудь придумать, но чем проще - тем легче с этим будет жить...
  158. --Поэтому просто сохраняет айпишники компьютеров из 403 аудитории
  159. --(в рамках лабы заполнил localhost'ом и фиктивными данными)
  160. create table AllowedIps(
  161.     ip varchar(16) primary key,
  162.     note nvarchar(255)
  163. )
  164. insert into AllowedIps(ip, note)
  165. values ('127.0.0.1', 'localhost'),
  166.        ('192.168.0.1', N'Компьютер из 403 №1'),
  167.        ('192.168.0.2', N'Компьютер из 403 №2'),
  168.        ('192.168.0.3', N'Компьютер из 403 №3')
  169.  
  170. --2.3) Таблицу аудита
  171. create table LogAuditTestAdmin(
  172.     eventData xml,
  173.     reason nvarchar(255)
  174. )
  175.  
  176.  
  177. --3) Пишем триггер
  178. --DROP TRIGGER if exists TestAdminLogonManager on all server
  179. CREATE OR ALTER TRIGGER TestAdminLogonManager
  180.     ON ALL SERVER
  181.     FOR LOGON
  182.     AS
  183. BEGIN
  184.     --current_user при заходе = guest, проверено)
  185.     if original_login() != 'TestAdmin'
  186.         return; --можно было WITH EXECUTE, но так красивее
  187.     declare @notAllowedReason nvarchar(255) = N'';
  188.  
  189.     declare @logonDatetime datetime = EVENTDATA()
  190.         .value('(/EVENT_INSTANCE/PostTime)[1]', 'datetime');
  191.  
  192.     if not exists(
  193.         select *
  194.         from [Laba4(5)].dbo.AllowedPeriods
  195.         where DATEDIFF(day, @logonDatetime, AllowedPeriods.start) % 14 = 0 --совпадает четность недели
  196.         and cast(@logonDatetime as time) between cast(start as time) and cast([end] as time)
  197.         )
  198.     begin
  199.         set @notAllowedReason = @notAllowedReason + N'+Попытка подключения вне учебного времени'
  200.     end;
  201.  
  202.     declare @userIp varchar(16) = EVENTDATA()
  203.         .value('(/EVENT_INSTANCE/ClientHost)[1]', 'varchar(16)')
  204.     if not exists(select *
  205.                   from [Laba4(5)].dbo.AllowedIps
  206.                   where ip = @userIp)
  207.     begin
  208.         set @notAllowedReason = @notAllowedReason + N'+Попытка подключения вне кабинета 403'
  209.     end;
  210.  
  211.     if @notAllowedReason != ''
  212.     begin
  213.         declare @eventData xml = cast(EVENTDATA() as xml);--Почему-то без приведения типа ругалось
  214.         rollback tran;
  215.         insert into [Laba4(5)].dbo.LogAuditTestAdmin
  216.         values (@eventData, @notAllowedReason);
  217.     end
  218.  
  219. END;
  220.  
  221.  
  222. --4) Тестируем
  223.  
  224. --4.0) Переносим хост сервера из 403 кабинета
  225. delete
  226. from AllowedIps
  227. where ip = '127.0.0.1'
  228. --НЕ ПРОВЕРЯЛ! А то потом вообще зайти не смогу...
  229.  
  230. --4.1) Пытаемся зайти и смотрим почему не заходит
  231. select *
  232. from LogAuditTestAdmin
  233.  
  234. --4.2) Резко проводим пару в час ночи
  235. insert into AllowedPeriods(start, [end], note)
  236. values (SYSDATETIME(), DATEADD(minute, 95, SYSDATETIME()), N'Тест')
  237.  
  238. select *
  239. from AllowedPeriods
  240.  
  241.  
  242. ------------------------------------------------------------------------------------------------
  243. ------------------------------------------------------------------------------------------------
  244. --Задание 3
  245.  
  246. --ИБ
  247. --DDL-триггер с каждой создаваемой в текущей базе таблицей связывает DML
  248. --триггер на вставку (подобен TrivialTrigger). Имя таблицы, на которой произошло
  249. --срабатывание, извлекается из свойства SqlTriggerContext.EventData. DML триггер
  250. --на вставку выдает сообщение на экран
  251. -- Хорошая статья:
  252. -- https://www.c-sharpcorner.com/article/how-to-create-clr-triggers-in-c-sharp-and-install-and-uninstall-clr-assembly-in-mssql/
  253.  
  254. --1) Напишем DML триггер на C# и зарегистрируем его на сервере
  255.  
  256. --1.1) Сам триггер вынес в отдельный проект на гитхабе
  257. --https://github.com/SeregaTheDed/DDL_TRIGGER_LAB
  258.  
  259.  
  260. --1.2) Регаем на сервере
  261. go
  262. sp_configure 'show advanced options', 1;
  263. GO
  264. RECONFIGURE;
  265. GO
  266. sp_configure 'clr enabled', 1;
  267. GO
  268. sp_configure 'clr strict security', 0;
  269. GO
  270. RECONFIGURE;
  271. GO
  272.  
  273. --drop trigger if exists trig_InsertPrint
  274. --drop assembly if exists DDL_TRIGGER_LAB
  275. CREATE ASSEMBLY DDL_TRIGGER_LAB
  276. from 'C:\Users\user\source\repos\DDL_TRIGGER_LAB\DDL_TRIGGER_LAB\bin\Debug\DDL_TRIGGER_LAB.dll'
  277. WITH PERMISSION_SET = SAFE
  278.  
  279.  
  280. --2) Создаем триггер DDL на создание таблиц
  281. create or alter trigger OnNewTableCreate
  282. on database
  283. for CREATE_TABLE
  284. as
  285. begin
  286.     declare @schemaName nvarchar(255) = EVENTDATA()
  287.         .value('(/EVENT_INSTANCE/SchemaName)[1]', 'nvarchar(255)')
  288.     declare @tableName nvarchar(255) = EVENTDATA()
  289.         .value('(/EVENT_INSTANCE/ObjectName)[1]', 'nvarchar(255)')
  290.     declare @salt nvarchar(50) = cast(sysdatetime() as nvarchar(50))--Иначе может быть одновременно только 1 триггер
  291.     set @salt = REPLACE(@salt, N'-', N'_');
  292.     set @salt = REPLACE(@salt, N' ', N'_');
  293.     set @salt = REPLACE(@salt, N':', N'_');
  294.     set @salt = REPLACE(@salt, N'.', N'_');
  295.     declare @triggerName nvarchar(560) = 'trig_InsertPrint_'+@salt+' '
  296.     print(@triggerName)--Чтобы было удобно удалять для тестов
  297.     declare @sqlCommand nvarchar(1000) =
  298.     'CREATE TRIGGER '+@triggerName+
  299.     'ON '+@schemaName+'.'+@tableName+' '+
  300.     'FOR INSERT
  301.     AS EXTERNAL NAME DDL_TRIGGER_LAB.[DDL_TRIGGER_LAB.Trigger_PrintTableNameOnInsert].PrintTableNameOnInsert'
  302.  
  303.     exec sp_executesql @sqlCommand
  304. end
  305.  
  306.  
  307. --3) Создаем тестовую таблицу
  308. --drop table if exists TestTable3
  309. create table TestTable3(
  310.     test nvarchar(123)
  311. )
  312. --drop trigger trig_InsertPrint_2023_12_03_03_45_30_6706610
  313.  
  314. --4) Тестим
  315. insert into TestTable3
  316. values ('123')
  317.  
  318.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement