Проблема с цепочкой учетных данных в Windows и .NET - PullRequest
1 голос
/ 11 мая 2011

Сводка проблемы

При запуске в пакетном режиме моя личность теряется, но (как действительно хороший скафандр) только до самого последнего момента.

Детали проблемы

У меня есть сценарий PowerShell, работающий на WinXpSp3, который запускает блок сценария (через Invoke-Command) на удаленной машине в качестве конкретного тестового пользователя (через параметр -Session) в фоновом режиме (через параметр -AsJob).Сеанс создается следующим образом:

New-PSSession -computername $myServer -credential $myCredential

Блок сценария выполняет ряд действий, кульминацией которых является запуск тестовой среды NUnit.В тестируемом коде C # записывается имя пользователя «myTestUser» (через Environment.UserName), поэтому учетные данные, предоставленные PowerShell, должным образом принимаются.Это еще раз подтверждается Process Explorer: проверка свойств nunit-console, выполняющих пакетные тесты, показывает, что он принадлежит myTestUser.

Тест включает в себя доступ к базе данных Sql Server 2008 R2;Строка подключения устанавливается с помощью вызова new SqlConnection(connectionString).Строка подключения настроена для проверки подлинности Windows и использует эту форму:

Data Source=<my_db_server_name>;Initial Catalog=<my_db_name>;Integrated Security=True;Persist Security Info=True

Несмотря на то, что я окончательно выдвинул учетные данные myTestUser вплоть до тестируемого кода C #, попытка доступа к БД не видит этиучетные данные, приводящие к этой ошибке: Ошибка входа для пользователя 'NT AUTHORITY \ ANONYMOUS LOGON'

Некоторая дополнительная информация:

  1. Я подтвердил, что тестовый пользователь(myTestUser) имеет разрешения БД, а тест NUnit способен получить доступ к БД. Когда я запускаю тест NUnit вручную (через графический интерфейс NUnit), вошедший в систему как myTestUser, тест работает правильно, и SqlProfiler четко показывает эту активность, когда myTestUser отображается в NTUserNamecolumn.
  2. Та же ошибка возникает, если я работаю локально, а не на удаленной машине.
  3. Та же ошибка возникает, если я работаю как я на своей локальной машине (то есть без параметра -credential).

Вопрос

Как я могу спасти myTestUser с краяи как получить доступ к БД?


2011.05.16 Обновление

Вот упрощенный пример, демонстрирующий ту же проблему.

Во-первых, моя тестовая программа DBFetchVersion, котораявыводит имя текущего пользователя и результаты простого запроса:

class Program
{
    const string connString = ...your connection string here... ;
    const string query = "SELECT getdate() [Date], substring(@@version,1,charindex('-',@@version)-1) +convert(varchar(100),SERVERPROPERTY('edition'))+ ' ' +convert(varchar(100),SERVERPROPERTY('productlevel')) [SQL Server Version], @@servicename [Service Name], @@servername [Server Host], db_name() [Database], user_name() [User], host_name() [Client]";

    static void Main(string[] args)
    {
        DataView dataView;
        using (var connection = new SqlConnection(connString))
        {
            Console.WriteLine("user = " + Environment.UserName);
            using (var dataAdapter = new SqlDataAdapter(query, connection))
            {
                var dataSet = new DataSet();
                try
                {
                    connection.Open();
                    dataAdapter.SelectCommand.CommandType = CommandType.Text;
                    dataAdapter.Fill(dataSet, query);
                }
                finally { if (connection.State == ConnectionState.Open) connection.Close(); }
                dataView = dataSet.Tables[0].DefaultView;
            }
            foreach (var item in dataView.Table.Rows[0].ItemArray)
                Console.WriteLine(item);
        }
    }
}

А вот скрипт Powershell, который вызывает вышеуказанную программу.

$scriptBlock = {
    & "...path to my executable...\DBFetchVersion\bin\Debug\DBFetchVersion.exe"
}

$serverName = ... my server name ...
$username = "testuser"
$password = ... my user password ...
$adjPwd = $password | ConvertTo-SecureString -asPlainText -Force
$testCred = (New-Object System.Management.Automation.PSCredential($username,$adjPwd))    
$mySession = New-PSSession -computername $serverName  -credential $testCred 

# Test Scenarios:
Invoke-Command $scriptBlock 
#Invoke-Command $scriptBlock -computername $serverName 
#Invoke-Command $scriptBlock -computername $serverName  -credential $testCred 
#Invoke-Command $scriptBlock -Session $mySession 

В списке из четырехв конце тестовые сценарии работает без комментариев, выводит мое имя пользователя и результаты запроса.DBFetchVersion по-прежнему сообщает, что я являюсь пользователем со второй строкой, но соединение с БД не удается с ошибкой «Вход в систему для пользователя NT AUTHORITY \ ANONYMOUS LOGON».Оставшиеся две строки сообщают имя пользователя «testuser», но обе сообщают об одном и том же сбое при входе в систему для соединения с БД.

То, что этот изолированный пример говорит мне, не то, что я думаю, что что-то содержит ошибки в Powershell, .NETили мой код, но есть что-то с механизмом аутентификации, которого я еще не понимаю, поскольку при указании другого компьютера или сеанса оба пути включают путь, который в некотором смысле должен иметь более надежную защиту.

2011.08.03 Обновление - Eureka!

Что ж, Мэтт правильно определил проблему double-hop в качестве виновника и CredSSP аутентификацию в качестве решения.К сожалению, как я быстро выяснил, CredSSP требует Windows 7, поэтому я решил настроить пару виртуальных машин в качестве песочницы.CredSSP, однако, был не из тех, кто легко отказался от своих секретов (по крайней мере, для меня), как я подробно описал в этом посте о ServerFault: Не удается заставить CredSSP-аутентификацию работать в PowerShell

Я наконец-то былсмог заставить аутентификацию CredSSP работать так, чтобы я мог вернуться к проблеме, которую я поставил здесь в этой теме.В качестве теста я использовал эти 3 блока скриптов, подключенных к скрипту PowerShell, который я предоставил выше:

$scriptBlockA = {
    Write-Host ("hello, world: {0}, {1}" -f $env:USERNAME, (hostname))
}

# Simple DB test, but requires SqlServer installed!
$scriptBlockB = {
    if (! (Get-PSSnapin | ? { $_.name -eq "SqlServerCmdletSnapin100" } ) )
    { Add-PSSnapin SqlServerCmdletSnapin100; }
    Invoke-Sqlcmd -Query "SELECT getdate() as [Now]" -ServerInstance CinDevDB5
}

# Indirect DB test; requires .NET but not SqlServer,
# plus DBFetchVersion in home dir for targeted user.
$scriptBlockC = {
    & ".\DBFetchVersion.exe"
}

Блок A работал с CredSSP или без него, так как двойной скачок отсутствует. Блоки B и C будут работать только с CredSSP, поскольку они оба пытаются получить доступ к удаленной базе данных. QED.

1 Ответ

0 голосов
/ 02 июня 2011

Вначале я прочитал это и подумал о проблеме «двойного прыжка», но дополнительная информация, возможно, заставляет меня усомниться в этом:?this:

& "...path to my executable...\DBFetchVersion\bin\Debug\DBFetchVersion.exe"

также работает с вашего локального компьютера (как вы или пользователь):

Add-PSSnapin SqlServerCmdletSnapin100;
Invoke-Sqlcmd -Query "SELECT getdate()" -ServerInstance Server

И какую операционную систему вы используете?Если это Windows 2008, и проблема заключается в двойном прыжке, вы можете использовать CredSSP, чтобы избежать этого.

...