Invoke-SQLCmd с разными учетными данными - PullRequest
6 голосов
/ 23 августа 2011

Справочная информация: Я запускаю сценарий локально, который должен быть запущен как SYSTEM, давайте не будем вдаваться в причины. :) Сценарий пытается проверить работоспособность моего кластера MSSQL простым запросом. Однако проблема, с которой я сталкиваюсь, заключается в том, что локальная учетная запись SYSTEM не имеет доступа к удаленной базе данных. На данный момент я попробовал несколько вещей, которые я сейчас расскажу, но я честен в отношении любого решения, которое имеет смысл. Если это означает создание локальной базы данных в базе данных, которая может ответить на мой простой запрос, это тоже хорошо.

Есть то, что я имею до сих пор:

$Server = 'myserver.domain.tld'
$Database = 'myDatabase'
$Query = 'SELECT DB_NAME() AS DataBaseName'
$Username = 'myDomain\myUsername'
$Password = 'myPasswordWithPlainText'
Invoke-SQLCmd -ServerInstance $Server -Database $Database -ConnectionTimeout 300 -QueryTimeout 600 -Query $Query -Username $Username -Password $Password

Результат: Invoke-Sqlcmd : Login failed for user 'myDomain\myUsername'

Может быть, Invoke-SQL не принимает аутентификацию Windows, как я думал, но он не использует -Credential. Тогда я попытался использовать Invoke-Command в качестве оболочки.

$Server = 'myserver.domain.tld'
$Database = 'myDatabase'
$Query = 'SELECT DB_NAME() AS DataBaseName'
$Username = 'myDomain\myUsername'
$Password = 'myPasswordWithPlainText'
$secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($Username, $secpasswd)
Invoke-Command -script {Invoke-SQLCmd -ServerInstance $Server -Database $Database -ConnectionTimeout 300 -QueryTimeout 600 -Query $Query} -Credential $Credential

Что меня достало: Invoke-Command : Parameter set cannot be resolved using the specified named parameters.

Итак ... Я застрял. Какие-нибудь мысли?

Ответы [ 6 ]

7 голосов
/ 23 августа 2011

Я использую Get-Credential, а затем Invoke-Command -AsJob, чтобы запустить скрипт из файла .sql. например,

$s = 'myserver.domain.tld';
$scriptpath = 'C:\myfile.sql';
$cred = Get-Credential -credential domain\user;
$sess = New-PSSession -ComputerName $s -Credential $cred -Authentication CredSSP -Name 'S1';
$job1 = Invoke-Command -Session $sess -FilePath $scriptpath -AsJob -JobName 'J1';
  # -ArgumentList $args;

Get-Job | Wait-Job;
Get-Job -Name 'J1';

Get-PSSession | Remove-Session;
Get-Job | Remove-Job;

Обратите внимание, однако, что строка $ cred будет запускать приглашение для подтверждения / аутентификации учетных данных - у меня также было имя базы данных в сценарии, поэтому я не уверен, как вы измените эту логику, чтобы направить сценарий в любую базу данных (если это необходимо для каждого сервера).

1 голос
/ 24 апреля 2014

Вы можете попробовать отправить работу и передать учетные данные.

#Submit the job with creds
$job = Start-Job {importsystemmodules; Invoke-Sqlcmd -Query 'select @@version'  -ServerInstance LOCALHOST} -Credential $creds | Get-Job | Wait-Job

#Receive the job
$jobInfo = Receive-Job -Job $job

Это сработало для меня.

1 голос
/ 23 августа 2011

Для такого рода вещей у нас был хороший успех с RUNAS / NETONLY

Не уверен, что у Powershell есть что-то эквивалентное (возможно, просто запустите Powershell с помощью RUNAS / NETONLY). Если вы встраиваете это в приложение, мы перезапустились, используя Windows API, чтобы сделать это: Как встроить функциональность RUNAS / NETONLY в (C # /. NET / WinForms) программу?

Также: http://www.theinfraguy.com/2011/08/three-uses-for-runas-netonly.html

0 голосов
/ 30 октября 2016

Нет необходимости удаленно входить в систему для запуска SQL-запроса.Вы можете использовать приведенную ниже функцию и передавать переменные по мере необходимости.Какую бы учетную запись не имели доступ, вы можете передать ее как учетные данные.(Работает как для аутентификации Windows, так и для SQL)

        $SQLInstance = "Instance Name"
        $Database = "Database"
        $ID = "User ID" 
        $Password = "Password"



     function Invoke-Sqlcommand 
        { 
            [CmdletBinding()] 
            param( 
            [Parameter(Position=0, Mandatory=$true)] [string]$ServerInstance, 
            [Parameter(Position=1, Mandatory=$false)] [string]$Database, 
            [Parameter(Position=2, Mandatory=$false)] [string]$Query, 
            [Parameter(Position=3, Mandatory=$false)] [string]$Username, 
            [Parameter(Position=4, Mandatory=$false)] [string]$Password, 
            [Parameter(Position=5, Mandatory=$false)] [Int32]$QueryTimeout=600, 
            [Parameter(Position=6, Mandatory=$false)] [Int32]$ConnectionTimeout=15, 
            [Parameter(Position=7, Mandatory=$false)] [ValidateScript({test-path $_})] [string]$InputFile, 
            [Parameter(Position=8, Mandatory=$false)] [ValidateSet("DataSet", "DataTable", "DataRow")] [string]$As="DataRow" 
            ) 

            if ($InputFile) 
            { 
                $filePath = $(resolve-path $InputFile).path 
                $Query =  [System.IO.File]::ReadAllText("$filePath") 
            } 

            $conn=new-object System.Data.SqlClient.SQLConnection 

            if ($Username) 
            { $ConnectionString = "Server={0};Database={1};User ID={2};Password={3};Trusted_Connection=False;Connect Timeout={4}" -f $ServerInstance,$Database,$Username,$Password,$ConnectionTimeout } 
            else 
            { $ConnectionString = "Server={0};Database={1};Integrated Security=True;Connect Timeout={2}" -f $ServerInstance,$Database,$ConnectionTimeout } 

            $conn.ConnectionString=$ConnectionString 

            #Following EventHandler is used for PRINT and RAISERROR T-SQL statements. Executed when -Verbose parameter specified by caller 
            if ($PSBoundParameters.Verbose) 
            { 
                $conn.FireInfoMessageEventOnUserErrors=$true 
                $handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {Write-Verbose "$($_)"} 
                $conn.add_InfoMessage($handler) 
            } 

            $conn.Open() 
            $cmd=new-object system.Data.SqlClient.SqlCommand($Query,$conn) 
            $cmd.CommandTimeout=$QueryTimeout 
            $ds=New-Object system.Data.DataSet 
            $da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd) 
            [void]$da.fill($ds) 
            $conn.Close() 
            switch ($As) 
            { 
                'DataSet'   { Write-Output ($ds) } 
                'DataTable' { Write-Output ($ds.Tables) } 
                'DataRow'   { Write-Output ($ds.Tables[0]) } 
            } 

        } 

Invoke-Sqlcommand -ServerInstance $SQLInstance -Database $Database -Query "Query Goes here" -Username $ID -Password $Password

Надеюсь, что это поможет.

0 голосов
/ 25 августа 2011

К сожалению, я попробовал все это (включая предложение Мэтта), а затем еще несколько, и я просто не могу заставить его работать при следующих параметрах. 1) Сценарий запускается из службы, работающей в качестве учетной записи SYSTEM. 2) Система находится в отдельном домене / подсети / и т. Д., Чем кластер SQL. 3) Запрос должен выполняться в реальном времени и возвращаться в реальном времени, поскольку запрос является лишь частью более крупного сценария.

Пока что я добавил полотенце и создал локальную учетную запись SQL для использования, а затем использовал Invoke-SQL как есть с параметрами -username и -password. Это не то, как я хотел справиться с ситуацией, но это то, что есть. Спасибо всем!

0 голосов
/ 23 августа 2011

, если вы еще не проверили, есть ли у пользователя доступ к БД: -)

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

Это не проверено: -)

$ConnectionString = "Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;"
$connection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString);
$command = New-Object System.Data.SqlClient.SqlCommand;

$command.Connection = $connection;
$command.CommandType = [System.Data.CommandType]::Text;
$command.CommandText = "SELECT DB_NAME() AS DataBaseName";

$connection.open();

$reader = $command.ExecuteReader()

While($reader.Read()){
    # do something with $reader
}

$connection.Close()
$reader.Close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...