基本的に、日常的な管理タスク用のPowershellスクリプトを実行するためのゲートウェイであるASP.NET(C#)アプリの作成に取り組んでいます。これらのスクリプトの一部はActiveDirectoryRSATモジュールを使用しており、ゲートウェイを介して呼び出されたときにこれらのコマンドレットの一部が正しく実行されないことがわかりました。トレースは、ドメインコントローラーへの接続が成功したことを示しているようですが、シャットダウンされています。 DCによって。
次のコードは、ユーザー名を指定するための1つのテキスト入力を持つASP.NETWebフォームです。基本的に、それは以下を行います:
- WebユーザーのIDを想定します(PowerShellによって継承されることが確認されています)
- PowerShellRunspaceとそのRunSpace内にパイプラインを作成します
- Get-ADUserコマンドレットを呼び出し、ユーザー名をIdentityパラメーターとして渡します
フォームの出力要素にユーザーの名前を読み込んで、成功を確認します。
protected void LookupButton_Click( object sender, EventArgs e ) { WindowsImpersonationContext impersonationContext = ((WindowsIdentity)User.Identity).Impersonate(); Runspace runspace; Pipeline pipe; try { runspace = new_runspace(); runspace.Open(); pipe = runspace.CreatePipeline(); Command cmd = new Command("Get-ADUser"); cmd.Parameters.Add(new CommandParameter("Identity", text_username.Text)); pipe.Commands.Add(cmd); PSObject ps_out = pipe.Invoke().First(); output.Text = ps_out.Properties["Name"].Value.ToString(); } catch( Exception ex ) { error.Text = ex.ToString(); } finally { impersonationContext.Undo(); } } private Runspace new_runspace( ) { InitialSessionState init_state = InitialSessionState.CreateDefault(); init_state.ThreadOptions = PSThreadOptions.UseCurrentThread; init_state.ImportPSModule(new[] { "ActiveDirectory" }); return RunspaceFactory.CreateRunspace(init_state); }
興味深い部分は、catchブロック(強調鉱山)で公開されたエラーメッセージの特定の表現です。
System.Management.Automation.CmdletInvocationException:サーバーに接続できません。これは、このサーバーが存在しないか、現在ダウンしているか、ActiveDirectoryWebサービスが実行されていないことが原因である可能性があります。---> Microsoft.ActiveDirectory.Management.ADServerDownException:サーバーに接続できません。これは、このサーバーが存在しないか、現在ダウンしているか、ActiveDirectoryWebサービスが実行されていないことが原因である可能性があります。---> System.ServiceModel.CommunicationException:ソケット接続が中止されました。これは、メッセージの処理エラー、リモートホストによる受信タイムアウトの超過、または根本的なネットワークリソースの問題が原因である可能性があります。ローカルソケットのタイムアウトは「00:01:59.6870000」でした。---> System.IO.IOException:読み取り操作が失敗しました。内部例外を参照してください。---> System.ServiceModel.CommunicationException:ソケット接続が中止されました。これは、メッセージの処理エラー、リモートホストによる受信タイムアウトの超過、または根本的なネットワークリソースの問題が原因である可能性があります。ローカルソケットのタイムアウトは「00:01:59.6870000」でした。--->System.Net.Sockets.SocketException:既存の接続がリモートホストによって強制的に閉じられました
上位レベルの例外はタイムアウトがあったことを示していますが、下位例外によって示されるタイムアウトはありませんでした(コマンドから戻るのに数秒しかかかりませんでした)。サーバーに到達できない場合は、最下位レベルの例外メッセージで同じように表示されますが、この特定の表現により、ここで何らかの認証(またはその他のセキュリティ)の問題が発生していると思われます。
2013年2月19日更新:ここで説明する偽装方法を使用すると、スクリプトは期待どおりに実行されます。これにより、問題は、Windows認証によって提供されるWindowsIdentityオブジェクトが、ADに対して本質的にRPC呼び出しを行うスクリプトにはおそらく不適切である可能性があると思われます。残念ながら、アプリケーションコードでユーザーのパスワードを処理する必要があるため、Windows認証を放棄することはあまり望ましくありません(これは私が望む責任ではありません)。
Windows authが正確に何を行っているのか、またはその使用によってどのような種類のなりすましが許可されているのかについてのドキュメントを見つけることができませんでした。Windows認証を使用しているときにこれを行うことは可能ですか、それともユーザーにパスワードの入力を要求する必要がありますか?