Header RSS-подписка на обновления сайта eMail-подписка на обновления сайта

Настройка безопасности для связанных серверов. Часть 4/4.


366bef3a

  • Другие части статьи:
  • 1
  • 2
  • 3
  • 4
  • вперед »
Опция 5. Сопоставления (мапирование) имен входа.

Наконец, наша «таинственная» 5-я опция. Вы, конечно, обратили внимание на довольно большой список расположенный на странице Security выше тех четырех радио-кнопок что были нами рассмотрены. До сих пор он оставался у нас пустым. А вот если им воспользоваться, то мы и получим 5-й вариант безопасности при подключении к удаленному серверу. Хотя лучше бы пронумеровать этот вариант числом 4.5. Потому что логика движка при выборе окончательного способа подключения будет такой:

  • если логин желающий выполнить распределенный запрос находится в упомянутом списке — вариант безопасности для него берется из этого самого списка;
  • если тот же логин в списке не обнаружен — в действие вступает настройка безопасности определяемая одной их четырех радио-кнопок расположенных ниже того же списка.

Такая логика работы объясняет причину существования предыдущей опции (безусловного запрета на подключение к удаленному серверу). Если бы разбираемого нами списка не существовало такая «тотально-запретительная» опция была бы лишена смысла, ведь с тем же успехом можно было бы просто не создавать linked server. С ним же, и с той же опцией мы прекрасно реализуем сценарий «вообще-то нельзя, но некоторым — можно». Обратите внимание, что список (для лучшей его идентификации я буду называть его списком мапированных логинов) всегда работает в связке с радио-кнопками. Первый задает режим безопасности для «избранных» пользователей, вторые — для всех остальных.

Вот, допустим, сейчас у нас, после нашего последнего эксперимента, радио-кнопкой выбран вариант Not be made. Поскольку список мапированных логинов у нас пуст, в настоящий момент никто (и Фрэнк в том числе) не способен через локальный сервер подключиться к удаленному. Попробуем сделать Фрэнка «избранным» пользователем оставив запрет на подключение для остальных пользователей. Но сначала давайте разберемся, почему список называется именно списком мапированных логинов? А это потому, что он одному локальному логину сопоставляет ровно один удаленный логин. А иными словами список мапирует первый во второй. Так же учтем, что удаленный сервер может работать по сценарию Windows Authentication, и тогда локальный логин может быть мапирован только в себя же (но на удаленном сервере), по причинам уже разобранным ранее. Но он может работать и по сценарию смешанной аутентификации, и тогда, как говорится, появляются варианты сопоставления. Отрадно отметить, что наш список без проблем покрывает оба варианта и позволяет каждому отдельному логину быть мапированным хоть так, хоть эдак.

Так вот, давайте вновь в admin-студии откроем требуемую страницу в окне свойств нашего связанного сервера. Не трогая более радио-кнопок (но проверив, что ими отмечена опция Not be made) щелкаем кнопку Add внизу списка. Переместившись благодаря этому уже внутрь списка в первой его колонке Local login выбираем из выпадающего списка локальный логин WINR2\frank. И ставим галочку во второй колонке, Impersonate. Обращаем внимание, что последнее наше действие приводит к блокировке двух оставшихся колонок списка, в том смысле что они становятся недоступными для ввода. Это потому, что, как мы уже выяснили, в сценарии «только Windows аутентификация» логин может быть на удаленной машине лишь самим собой, и никак иначе. И никакие логины/пароли для него указывать не требуется.

Linked Server Properties_Security_Login_mappings_with_Impersonate

Щелкаем OK, на предупреждение о провале теста подключения к удаленному серверу не реагируем — No. Выполняем из frank-студии наш всегдашний тест, видим:

LoginName   DB_UserName
WINR2\frank frank

Ожидаемо, ведь Фрэнк теперь «особенный», ему можно. Если вы заподозрили, что финальный и практический итог нашего текущего эксперимента полностью идентичен таковому в случае самой первой опции из рассмотренных нами (Опция 1. Be made using the login's current security context) то ваши подозрения полностью оправданы. И результат, и «физика процесса» идентичны на 100%. Разница, как уже было сказано, что там такая установка действовала для всех пользователей локального сервера, а здесь — для одного.

Вернемся в admin-студии на страницу Security и уберем в единственной строке списка галочку в колонке Impersonate. Это сделает доступными для ввода две следующие колонки, в первой из которых (Remote User) давайте укажем mary, а во второй (Remote Password) введем пароль этого логина на удаленном компьютере.

Если вам кажется, что предпоследнюю колонку, вообще-то и по хорошему следовало назвать Remote Login, а не Remote User (ведь пароли следующие вслед за нею и с ней же, несомненно, связанные есть атрибут именно логинов, а не юзеров) то вы совершенно правы, мы сюда ввели (и должны вводить) именно Login удаленного сервера, а не User удаленной базы. Более того, при объяснении назначения той же колонки в Books Online сказано:
The Remote User must be a SQL Server Authentication login...
Да, вот так, юзер должен быть логином. Только не спрашивайте у автора, как такое может быть. Кроме составителя интерфейса студии на этот вопрос все-равно никто не ответит.

Linked Server Properties_Security_Login_mappings_with_Remote_Login

Снова OK, снова No и снова тест из frank-студии. На сей раз получаем:

LoginName   DB_UserName
mary        mary

И вновь вы правы, мы получили результаты идентичные второй из рассмотренных нами опции (Опция 2. Be made using this security context). И механизмы вовлеченные в получение такого результата тоже были идентичны. И — да, «там для всех», «тут для одного», вы уже все это знаете.

Теперь — смоделируем такую ситуацию. Допустим на локальном сервере есть только один пользователь — Фрэнк. Ну то есть он физически один. И рассмотрим при таком условии две возможные группы настроек безопасного подключения:

  • Группа A
    • настройка A1: в списке — Local login=WINR2\frank, Impersonate=check; радио-кнопки=Not be made;
    • настройка A2: список — пустой; радио-кнопки=Be made using the login's current security context;
  • Группа B
    • настройка B1: в списке — Local login=WINR2\frank, Impersonate=blank, Remote User=mary, Remote Password=<пароль_для_mary>; радио-кнопки=Not be made;
    • настройка B2: список — пустой; радио-кнопки=Be made using this security context, поля Remote Login и With password — mary и <пароль_для_mary> соответственно;

А спрашивается в задаче — с учетом нашего допущения, есть ли разница между настройками A1-A2 и настройками B1-B2? На первый взгляд в каждой паре можно выбрать любую цифру и результат будет идентичен. Более того, мы эту идентичность подтвердили экспериментально! А тем не менее разница есть. Но проявится она при особых условиях, а именно: если мы на локальном сервере удалим логин Фрэнка (возможно по ошибке?) и тут же его восстановим как он был. Вот тогда в вариантах A1/B1 Фрэнк теряет возможность подключения к удаленному серверу, а в вариантах A2/B2 он продолжит свою работу как ни в чем не бывало. Это потому, что при удалении логин тут же вычищается из списков мапированных логинов. И, понятно, движок не утруждает себя запоминаем что, мол, «такой-то логин был в списке такого связанного сервера». Это совершенно бессмысленно, т.к. если мы, как в разбираемом сценарии, даже тут же восстановим ошибочно удаленный логин Фрэнка, серверу-то откуда знать, что «Фрэнк-старый» и «Фрэнк-новый» одно и тоже лицо? Будьте любезны, новому логину все необходимые права раздать повторно, в том числе включить его в необходимые списки сопоставлений. Ну а настройки A2/B2 начинают «обслуживать» каждый новый логин с момента его возникновения, никаких дополнительных телодвижений не требуется. Этот маленький нюанс может быть большими «граблями» в серьезной распределенной системе с высокой «текучкой юзеров».

Еще вопрос, который вызывает непонятное колебание в ответе у SQL-администраторов/SQL-разработчиков: если настройки безопасного подключения максимально просты — список пустой и выбрана «общая» опция Not be made — и мы заходим на локальный сервер как администраторы (пусть, для усиления картины, мы администраторы локального SQL сервера, удаленного SQL сервера и домена в который входят оба сервера), то что же, при таких условиях, мы не сможем обратиться к удаленному серверу через локальный? Да нет конечно же, не сможем! Причем здесь наш огромный список полномочий если мы сами приказали локальному серверу «ни за что не подключаться к удаленному!»? Вот он наш приказ и честно выполнит, какие претензии? Почему-то бытует мнение, что если связанный сервер создан то уж администратор обязательно сможет к нему подключиться при любых раскладах (разумеется, мы опускаем вопросы наличия физического подключения одной точки к другой, это очевидно). Отнюдь, как видите. Да и более того, мы без проблем можем создать окружение в котором тот же Фрэнк (рядовой юзер) сможет обращаться к удаленному источнику данных, а мы, администраторы — нет. Правда зачем же мы себе на голову будем подобное окружение создавать, верно? ;)

Далее, мы уже поняли что первая и вторая из рассмотренных нами опций может назначаться на «персональном» уровне — уровне отдельного логина. А нельзя ли на том же уровне запретить доступ к удаленному серверу? Первое что приходит в голову, это такая идея: при внесении подобного логина в список мапированных логинов не ставить галочку Impersonate, но и не заполнять поля Remote User/Remote Password. Однако, увы, такую запись внести не удастся:

The login mappings should either be impersonate or have a remote login name.

Надо действовать хитрее: Impersonate не ставить, а Remote User/Remote Password заполнить откровенным «бредом», который никогда и ни при каких обстоятельствах стать валидным логином удаленного сервера не сможет. При внесении записи в список мапированных логинов валидность удаленного логина не проверяется, и, соответственно, указанный в первой колонке списка логин локальный теряет возможность подключения. Правда, для корректности, отметим, что это не есть запрет подключения в чистом виде, как это делает опция Not be made. Попытка подключения все же будет, но она гарантированно будет отвергнута удаленным сервером. Так что с практической точки зрения результат достигнут, отдельный локальный логин не может осуществить удаленное подключение.

Вариант второй достижения того же самого — отказаться от студии и внести «запретительный» логин в список мапированных логинов через T-SQL код:

1
2
3
USE [master]
GO
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'WINR2\MSSQL2', @locallogin = N'WINR2\frank', @useself = N'False'

Тут, как вы можете видеть, подход куда как более близок к «чистому»: и галочка Impersonate очищена (параметр @useself), и удаленных логинов/пароля нет вообще. По сути, начиная с этого момента локальный логин WINR2\frank переведен в режим «Опция 3. Be made without using a security context» при подключении к удаленному серверу WINR2\MSSQL2. Т.е. он будет пытаться подключиться к нему с «пустым» пользователем, что, разумеется, обречено на провал.

Заключение

Ну что же, с точки зрения автора поставленная цель достигнута, возможные опции страницы Security окна настройки связанного сервера разобраны совершенно досконально. Если резюмировать и составить для себя своеобразную «шпаргалку» методов подключения сервера локального к серверу удаленному, то в ней мы отметим, что первый может подключаться ко второму:

  • вообще не подключаться ни при каких обстоятельствах
  • с «пустым» (или, если хотите, анонимным) пользователем
  • с тем же Windows-пользователем что подключился к самому локальному серверу
  • с конкретным и четко обозначенным (обязательно!) удаленным пользователем (более правильно — удаленным SQL логином)

Указанные четыре варианта могут очень гибко комбинироваться, так что часть логинов на локальном сервере будут подключаться одним способом, вторая часть — вторым способом, и даже может быть часть третья, с третьим же способом подключения.

Так же мы отметили себе, что в случае если удаленной точкой выступает SQL Server (или вообще «серьезная система») указанный выше список сокращается на один пункт, а именно: вариант с «пустым» пользователем становится практически (но не теоретически!) равный пункту первому, который в данных обстоятельствах становится намного более предпочтительным.

Автор благодарит своих читателей за внимание проявленное к его труду, и желает всем быстрых и безопасных SQL-запросов (в особенности распределенных). Увидимся, пока!

  • Другие части статьи:
  • 1
  • 2
  • 3
  • 4
  • вперед »