Pull to refresh

Дело о загадочном Access denied

Reading time 4 min
Views 47K
Утром в службу поддержки обратился один из разработчиков корпоративного приложения. Он не мог сделать копию с базы данных MS SQL Server, и просил выяснить причину ошибки.

Первое с чего стоит начать — проверить ошибку на воспроизводимость.
Попробуем снять копию командой:
BACKUP DATABASE [SDB] TO DISK=N'\\FS1\Backup\sdb_full.bak' WITH COPY_ONLY


Что еще за COPY_ONLY?
WITH COPY_ONLY — очень полезный ключ. Он позволит не нарушить в системе резервного копирования последовательность дифференциальных копий


Действительно, попытка снять копию заканчивалась ошибкой:


Что может вызвать такую проблему?

SQL Server запускается от встроенной учетной записи «Network Service»

На всякий случай проверяем разрешение имени сервера FS1 по короткому имени и по FQDN. Оба имени разрешаются и, что важно, указывают на один и тот же сервер. Открываем сетевую папку, проверяем разрешения на NTFS и Share Permissions. Все в порядке, учетная запись сервера SQL1 имеет разрешение на запись.

Может быть проблемы с NTLM, Kerberos? Попробуем снять резервную копию, используя FQDN сервера.

BACKUP DATABASE [SDB] TO DISK=N'\\FS1.contoso.test\Backup\sdb_full.bak' WITH COPY_ONLY



Интересно. С использованием FQDN резервная копия успешно создалась. Что это значит? Разве что ситуация стала еще более запутанной.

SQL Server перезапускать в рабочее время нельзя. Оставаться в ночь не хотелось бы.

Когда ничего непонятно, лучший друг администратора — Wireshark или Microsoft Network Monitor. Если снять хороший дамп, то можно или разобраться, или уж запутаться так запутаться.

Ставить на ответственный сервер Microsoft Network Monitor теоретически безопасное мероприятие, но жизнь так часто вносит коррективы в самые безопасные начинания.

Перезагружаться нельзя, ставить монитор нежелательно. Тогда воспользуемся службой Windows Event Tracing.

Включили трассировку:
netsh trace start persistent=yes capture=yes tracefile=c:\temp\trace.etl

Повторили команду резервного копирования несколько раз:
BACKUP DATABASE [SDB] TO DISK=N'\\FS1\Backup\sdb_full.bak' WITH COPY_ONLY
BACKUP DATABASE [SDB] TO DISK=N'\\FS1\Backup\sdb_full.bak' WITH COPY_ONLY
BACKUP DATABASE [SDB] TO DISK=N'\\FS1\Backup\sdb_full.bak' WITH COPY_ONLY

Остановили трассировку:
netsh trace stop



Открываем файл в Microsoft Network Monitor на рабочей станции администратора:


Каждый раз при попытке снятия копии появляется событие KDC_ERR_PREAUTH_REQUIRED с загадочным пользователем DBAdmin. Это не учетная запись сотрудника, администратора, под ней не запускается SQL Server.
KDC_ERR_PREAUTH_REQUIRED означает, что учетные данные неверны.

Но резервное копирование выполняется в контексте службы «MS SQL Server», а она запущена под «Network Service». Причем здесь DBAdmin?

В Windows есть «Диспетчер учетных данных», он же «Credentials Manager», позволяющий сохранять учетные данные для различных сетевых ресурсов. Его можно вызвать командой «control userpasswords2» или «netplwiz»:


Давайте проверим, нет ли в контексте учетной записи компьютера «SQL1\Network Service» сохраненных альтернативных учетных данных для сервера FS1.

Для того, чтобы запустить процесс от имени другого пользователя, воспользуемся psexec.

Если запустить psexec с ключем "-s", мы попадем в контекст «Local System». Не подойдет.

Для того, чтобы попасть в контекст «Network Service» запускаем утилиту со следующими ключами:
psExec.exe  -i  -u “nt authority\network service” cmd.exe





Проверим, повторяется ли в контексте «Network Service» ошибка Access Denied при обращении к серверу FS1:


Ошибка воспроизводится.

Проверим сохраненные учетные данные. Запустить «control userpasswords2» без колдовства с Explorer не получится. Да и не надо, для работы с «Credentials Manager» из командной строки есть утилита cmdkey.exe.

Для того, чтобы вывести сохраненные учетные данные выполним команду:
cmdkey /list



Никаких сохраненных учетных данных не обнаружено. Еще интереснее.

Итак, что мы знаем на текущий момент:
  1. В контексте учетной записи компьютера «SQL1\Network Service» при обращении по протоколу SMB к серверу FS1 возвращается ошибка Access Denied
  2. При обращении к серверу по FQDN FS1.contoso.test ошибка не возвращается
  3. Обращение к серверу FS1 происходит с использованием учетной записи DBAdmin, которая нигде в явном виде не используется
  4. В контексте «SQL1\Network Service» в Credentials Manager учетные данные не сохранялись

Подождите, а ведь учетные данные можно сохранить не только в Credentials Manager, но и в памяти службы «Lanman Workstation».

Если подключить диск с параметром /savecred, то учетные данные сохранятся в Credentials Manager:

net use \\FS1\Backup /persistent:yes /savecred  

Если опустить параметр /savecred, то учетные данные сохранятся в памяти службы до перезагрузки
net use \\FS1\Backup /persistent:yes /user:DBAdmin 

Проверим нет ли у нас сохраненных подключений:
net use



Есть! Теперь понятно, почему при обращении к FS1 возвращалась ошибка, а к FS1.contoso.test — нет.

Удалим сохраненные подключения:

net use * /delete


Проверяем резервное копирование:


Проблема решена.

А в чем же было дело? Причина ошибки весьма нетривиальна. Внутри корпоративного приложения от имени SQL Server был подключен сетевой диск под пользователем DBAdmin, который из-за ошибки в приложении не был в дальнейшем отключен. Спустя некоторое время у пользователя DBAdmin, вероятно сменился пароль, или сервер был перезагружен. И вот он, загадочный Access denied!

Какие для себя можно сделать выводы?
  1. Когда вы выполняете резервное копирование SQL Server, обращение к сетевым ресурсам производится от имени учетной записи службы SQL Server, а не от пользователя, запустившего команду BACKUP DATABASE. Следует помнить об этом, настраивая разрешения.
  2. Всегда снимайте дополнительные полные резервные копии с ключом WITH COPY_ONLY. SQL Server помечает страницы данных, измененные после полного резервного копирования, и в дифференциальную копию попадают только измененные страницы. Логично, что после каждого полного резервного копирования, состояние страниц очищается. Ключ позволяет не очищать отметку страниц, и последовательность не будет нарушена.
  3. В случае ошибки «Access denied» не лишним будет проверить, повторяется ли ошибка и по имени узла, по FQDN, по IP адресу.
  4. Вы можете попасть в контекст безопасности нужной учетной записи, запустив psexec с ключем -U.
  5. Для вывода учетных данных из службы хранения ключей используется утилита cmdkey.
  6. Для вывода сохраненных подключенных сетевых подключений используйте команду net use.


Спасибо за внимание.

Спасибо ildarz, sabin за содержательные комментарии, устранение неточностей и подсказки.
Tags:
Hubs:
+26
Comments 36
Comments Comments 36

Articles