25

Вдохновленный различные вопросы, связанные схемы, которые я видел ...SQL Server: как разрешить схемы?

Ownership chaining позволяет мне GRANT EXECUTE на хранимую процедуру без явного разрешения на таблицах, которые я использую, если оба хранимые процедуры и таблицы находятся в одной и той же схеме.

Если мы используем отдельные схемы, тогда я должен явно указать GRANT XXX в таблицах разных схем. Этот пример демонстрирует пример цепной привязки. Это означает, что сохраненный исполняющий процесс proc пользователь может напрямую читать/писать ваши таблицы.

Это будет иметь прямой доступ к вашим переменным экземпляра в классе, минуя геттер/сеттеры, прерывая инкапсуляцию.

Мы также используем безопасность на уровне строк, чтобы ограничить то, что кто-то видит, и применяем это в хранимых процедурах.

Итак, как мы можем поддерживать разделение схемы и предотвращать прямой доступ к таблице?

Конечно, вопрос не будет применяться, если вы используете ORM или не используете хранимые процедуры. Но я не с просьбой, если я должен использовать ОРМ или хранимую процедуру в случае, если кто-то чувствует необходимость просветить меня ...

Edit, пример

CREATE USER OwnsMultiSchema WITHOUT LOGIN 
GO 
CREATE SCHEMA MultiSchema1 AUTHORIZATION OwnsMultiSchema 
GO 
CREATE SCHEMA MultiSchema2 AUTHORIZATION OwnsMultiSchema 
GO 

CREATE USER OwnsOtherSchema WITHOUT LOGIN 
GO 
CREATE SCHEMA OtherSchema AUTHORIZATION OwnsOtherSchema 
GO 

CREATE TABLE MultiSchema1.T1 (foo int) 
GO 
CREATE TABLE MultiSchema2.T2 (foo int) 
GO 
CREATE TABLE OtherSchema.TA (foo int) 
GO 

CREATE PROC MultiSchema1.P1 
AS 
SELECT * FROM MultiSchema1.T1 
SELECT * FROM MultiSchema2.T2 
SELECT * FROM OtherSchema.TA 
Go 
EXEC AS USER = 'OwnsMultiSchema' 
GO 
--gives error on OtherSchema 
EXEC MultiSchema1.P1 
GO 
REVERT 
GO 

CREATE PROC OtherSchema.PA 
AS 
SELECT * FROM MultiSchema1.T1 
SELECT * FROM MultiSchema2.T2 
SELECT * FROM OtherSchema.TA 
Go 
GRANT EXEC ON OtherSchema.PA TO OwnsMultiSchema 
GO 
EXEC AS USER = 'OwnsMultiSchema' 
GO 
--works 
EXEC OtherSchema.PA 
GO 
REVERT 
GO 

Edit 2:

  • мы не используем «перекрестного владения базами данных цепочки»
  • Роу уровень безопасности является отвлекающим маневром и не имеет значения: мы не используем его везде
+2

Возможно ли, чтобы вы указали кодированный пример сценария отдельной схемы, который вы описываете для ясности, пожалуйста? В вашем сценарии, имеют ли две отдельные схемы один и тот же владелец? –

+0

Зачем голосовать за serverfault? Это для кодовых обезьян, а не системных администраторов ... – gbn

+0

@ Джон Сансом: да, я это сделаю. – gbn

ответ

21

Я боюсь, что либо ваше описание или ваша концепция цепочки владения не ясно, поэтому позвольте мне начать с этого:

«Собственность Chaining» просто ссылается на тот факт, что при выполнении хранимой процедуры (или View) на SQL Server, текущая исполняемая партия временно получает права/разрешения владельца sProc (или владельца схемы sProc) при выполнении этого кода SQL. Таким образом, в случае sProc Пользователь не может использовать эти привилегии для выполнения чего-либо, что код sProc не реализует для них. Обратите внимание, что он никогда не приобретает Удостоверение личности владельца, только его права временно (однако, EXECUTE AS ... делает это).

Таким образом, типичный подход использовать это для безопасности заключается в следующем:

  1. Поместите все таблицы данных (и все соображения не относящаяся к безопасности, а) в свою собственную схему, давайте назовем его [данные ] (хотя обычно используется [dbo], потому что он уже существует и слишком привилегирован для схемы пользователя). Убедитесь, что никакие существующие пользователи, схемы или владельцы не имеют доступа к этой [данные] схеме.

  2. Создайте схему, называемую [exec] для всех sProcs (и/или, возможно, любых представлений безопасности). Убедитесь, что владелец этой схемы имеет доступ к схеме [data] (это легко сделать, если вы сделаете dbo владельцем этой схемы).

  3. Создайте новую db-роль под названием «Пользователи» и дайте ей EXECUTE доступ к схеме [exec]. Теперь добавьте всех пользователей в эту роль. Убедитесь, что ваши пользователи имеют только права на подключение и не имеют никакого доступа к какой-либо другой схеме, включая [dbo].

Теперь ваши пользователи могут получить доступ к данным только путем выполнения sProcs в [exec]. Они не могут получить доступ к каким-либо другим данным или выполнять какие-либо другие объекты.

Я не уверен, отвечает ли это на ваш вопрос (потому что я был не уверен, что вопрос был точно), поэтому не стесняйтесь перенаправлять меня.


Что касается безопасности на уровне строк, вот как я всегда делаю это со схемой безопасности выше:

  1. Я всегда реализации безопасности на уровне строк как ряд соображений, что зеркально-обруча каждой таблицы и сравнить идентификатор пользователя (обычно с Suser_Sname() или одним из других) в список безопасности, введенный с помощью кода безопасности самой строки. Это Security-Views.

  2. Создайте новую схему под названием [rows], дайте ее владельцу доступ к схеме [data] и ничего больше. Поместите все Security-Views в эту схему.

  3. Отменить доступ владельца [exec] к схеме [data] и предоставить ему доступ к данным в схему [rows].

Выполнено. Теперь безопасность на уровне строк была реализована путем прозрачного скольжения между sProcs и таблицами.


Наконец, здесь хранится Procure, что я использую, чтобы помочь мне вспомнить, сколько из этого неясного StuFF безопасности работ и взаимодействует с самими собой (упсом, исправленная версия коды):

CREATE proc [TestCnxOnly].[spShowProc_Security_NoEX] as 
--no "With Execute as Owner" for this version 
--create User [UserNoLogin] without login 
--Grant connect on database :: TestSecurity to Guest 
--alter database TestSecurity set trustworthy on 

--Show current user context: 
select current_user as current_ 
, session_user as session 
, user_name() as _name 
, suser_name() as [suser (sproc)] 
, suser_sname() as sname 
, system_user as system_ 


--Execute As Login = 'UserNoLogin' 
select current_user as current_ 
, session_user as session 
, user_name() as _name 
, suser_name() as [suser (after exec as)] 
, suser_sname() as sname 
, system_user as system_ 

EXEC('select current_user as current_ 
, session_user as session 
, user_name() as _name 
, suser_name() as [suser (in Exec(sql))] 
, suser_sname() as sname 
, system_user as system_') 

EXEC sp_ExecuteSQL N'select current_user as current_ 
, session_user as session 
, user_name() as _name 
, suser_name() as [suser (in sp_Executesql)] 
, suser_sname() as sname 
, system_user as system_' 

--Revert 
select current_user as current_ 
, session_user as session 
, user_name() as _name 
, suser_name() as [suser (aftr revert)] 
, suser_sname() as sname 
, system_user as system_ 

[EDIT: исправленная версия кода)

+0

. Я обычно понимаю цепочку прав собственности в этом примере: не проверена сохраненная proc в таблицах доступа schema1 в schema1 = права таблицы (включая DENY). Проверяются таблицы, например, schema2. Мой пример показывает, что с EXEC MultiSchema1.P1 – gbn

+0

Мой собственный пример, который пересек с вашим ответом. Бит, который мне не хватало, заключается в том, что если * владелец * соответствующих схем одинаковый, тогда права не проверяются. Тогда это смысл разделения пользователь/схема, который я действительно должен был прочитать. Тем не менее, у нас есть предварительный SQL 2005 свес и не думал об этом через – gbn

+0

Этот пример работает, потому что он находится в одной и той же схеме, таким образом, хранимые proc и таблица имеют один и тот же владелец, поэтому доступ разрешен, потому что у владельца всегда есть * default * права доступа к своим вещам. Обратите внимание, однако, что это не исключает DENY и т. Д. Все, что может остановить владельца схемы, безусловно, остановит сохраненные procs, которыми они владеют. – RBarryYoung

4

Вы можете:

Grant Execute On Schema::[schema_name] To [user_name] 

, чтобы позволить пользователю выполнять какие-либо процедуры в схеме. Если вы не хотите, чтобы он мог выполнить все из них, вы можете явно запретить выполнение конкретной процедуры пользователю. В этом случае отказ будет иметь приоритет.

+0

Правильно, но как насчет таблиц в разных схемах, используемых хранимыми процедурами? Я не хочу DENY любых прав. – gbn

8

My 2c: Собственность цепочки является наследием. Это датируется днями, когда альтернатив не было, и по сравнению с сегодняшними альтернативами это небезопасно и грубо.

Я говорю, что альтернатива - это не разрешения схемы, альтернативой является подписание кода. При подписи кода вы можете предоставить необходимые разрешения для подписи процедуры и предоставить широкий доступ к выполнению процедуры, пока доступ к данным жестко контролируется. Подписание кода предлагает более гранулированный и более точный контроль, и его нельзя злоупотреблять, как может быть привязка к целям. Он работает внутри схемы, он работает по схеме, он работает через базу данных и не требует, чтобы открытая огромная дыра в области защиты от перекрестного доступа к базе данных. И это не требует захвата владения объектом для целей доступа: владельцем процедуры может быть любой пользователь.

Что касается вашего второго вопроса о безопасности на уровне строк: безопасность на уровне строк на самом деле не существует в версиях SQL Server 2014 и ранее, как функция, предлагаемая движком. У вас есть различные способы обхода проблемы, и эти методы работы работают лучше с подписями кода, чем с цепочкой прав собственности. Поскольку sys.login_token содержит подписи и подписи контекста, вы можете выполнять более сложные проверки, чем вы могли бы в контексте цепочки владения.

С версии 2016 SQL Server полностью поддерживает row level security.

+0

Безопасность уровня строки на самом деле является красной селедкой .. мы также используем SUSER_SNAME через JOINs из таблиц безопасности для управления доступом. – gbn

+0

Это «устаревший» бит, а затем время/усилие/лень, почему я не следил. + 1 в любом случае. благодаря – gbn