web-dev-qa-db-ja.com

Invoke-Sqlcmdに別のWindowsアカウントを使用する

SQL Serverと対話する必要があるPowershellスクリプトを作成しようとしているため、スクリプトの一部にinvoke-sqlcmdが含まれます。ただし、スクリプトをSQL Serverのジョブとしてスケジュールすることはできないため、認証に使用されるWindowsアカウントとして機能するエージェントを利用します。代わりに、任意のWindowsアカウントで別のサービスを使用して実行されます。 invoke-sqlcmdのドキュメントには、-Usernameおよび-PasswordパラメーターはWindowsではなくSQL Server認証用であり、SQL Serverパラメーターが指定されていない場合、認証用のスクリプトを実行しているWindowsアカウントをデフォルトで使用することが記載されています。

Invoke-sqlcmdが認証に使用されているアカウントではなく、認証に任意のWindowsアカウントを使用できるようにする方法はありますか?可能な解決策は、スクリプトを実行するSQL Serverインスタンスにアカウントを作成し、コマンドでSQL Server認証オプションを使用することですが、理想的にはそうする必要はありません。他のいくつかの調査でも、証明書は追跡可能なオプションである可能性があることが示されていますが、invoke-sqlcmdが証明書を取得したり、提案された方法で証明書を利用したりできるとは思いません。私はここで間違っているかもしれません。

4
Dylan Bacon

ジョブを実行するアカウントに、クエリを実行するために必要なSQL Serverへのアクセス許可を付与できます。それが一番簡単でしょう。タスクスケジューラを使用する場合は、使用するアカウントを指定する方法も用意されています。

次善の策は、SQL認証を使用することです。

最後に、PowerShellを使用して新しいスレッドを呼び出し、別のWindowsアカウントで実行し、そのスレッドでInvoke-sqlを使用できます。ただし、パスワードは何らかの方法で保存する必要があります(通常はファイルで暗号化されます)。これは最善の解決策ではなく、私が使用することをお勧めするものでもありません。

3
Jonathan Fite

別の方法として、Invoke-Sqlcmdを使用するライブラリ用にStart-Jobのラッパーを作成しました。

function Invoke-InternalSqlcmd {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)][string] $Query,
        [Parameter(Mandatory=$true)][string] $Database,
        [Parameter(Mandatory=$false)][System.Management.Automation.PSCredential] $Credential
    )

    if (-not $Credential) {
        return Invoke-SqlCmd -Query $Query -Database $Database
    }
    else {
        $ScriptBlock = {
            param($Query,$Database) 
            $ErrorActionPreference = 'Stop';

            return @{ Result = Invoke-SqlCmd -Query $Query -Database $Database }
        }

        $Job = Start-Job -Credential $Credential -ScriptBlock $ScriptBlock -ArgumentList $Query,$Database
        $JobResult = Wait-Job $Job;

        if ($JobResult.State -eq 'Completed') {
            return (Receive-Job $Job).Result
        }

        throw [Exception]::new("Error occurred while executing sql as $($Credential.UserName) $([System.Environment]::NewLine)$($JobResult.ChildJobs[0].JobStateInfo.Reason)", $JobResult.ChildJobs[0].JobStateInfo.Reason)
    }
}

長所

  • 動作します!
  • WinRMを使用しない
  • Invoke-Sqlcmdが返す正確な結果を返します
  • エラーを返します

短所

  • PSジョブを実行すると、厄介なオーバーヘッドが発生します。 2-10秒の間のどこでも。これは大した問題ではないかもしれませんが、実行しているコードが実行される時間の長さに依存します。
  • ErrorActionPreferenceを尊重せず、常にエラーが発生します。必要に応じて修正できます。

WinRMにアクセスできないロックダウン環境で実行しています。タスクが長時間実行されているため、これは私のニーズに適しています。より良いパフォーマンスが必要な場合は、WinRMを使用して問題がなければ、ジョブコードをRunspacesに簡単に置き換えることができます。

0
elexis