web-dev-qa-db-ja.com

ユーザー「NT AUTHORITY \ ANONYMOUS LOGON」のログインに失敗しました

Windows Server 2012R2およびSQL Server 2014 Enterpriseバックエンドを実行しているオペレーションサーバーがあります。このサーバーは、SQLエージェントジョブによって呼び出されるcmdファイルを介して新しいコードを他の運用サーバーに展開するために使用されます。サーバーはすべて同じドメイン上にあります。

サーバーAは、Windows Server 2008R2およびSQL Server 2008R2バックエンドを実行します。このサーバーには、サーバーBのデータベースに接続するリンクサーバーがあり、Aと同じバージョンのOSとSQL Serverを実行しています。リンクサーバーはオプション@ useself = TRUEで構成されています。

  • 3つのサーバーはすべて、委任が有効なサービスアカウントを使用します。
  • このサービスアカウントには、3つのSQL Serverインスタンスすべてに対する特権があります。
  • 3つのサーバーすべてに、そのアカウントで構成されたSPNがあり、関連するMSSQLSVCサービスにKerberosを使用するように委任されています。

それぞれに対して次のコマンドを実行すると、「Kerberos」が返されます

    SELECT auth_scheme FROM sys.dm_exec_connections WHERE session_id = @@spid

さらに、これらのサーバーから他のサーバーに問題なくTelnetやpingなどを実行できます。すべてが接続されています。コードの展開に問題が発生したことはありません。リンクサーバーは頻繁に参照され、問題は発生しません... 1つのシナリオを除いて、理由がわかりません。

ダブルホップシナリオ

  1. オペレーションサーバー上のSQLエージェントジョブは、SQLエージェントサービスアカウント以外のsysadminによってアドホックに実行され、オペレーションサーバー上でもcmdファイルを実行します。
  2. SQLエージェントジョブは、SQLエージェントサービスアカウントを "実行する"ように構成されており、sa特権を持っています。
  3. デプロイされるコードは、オペレーションサーバーの.sqlファイルから取得されます。
  4. CmdファイルはSQLCMDを呼び出して、サーバーAに対して.sqlファイル内のコードを実行します。
  5. .sqlファイルのコードリンクサーバーを参照でエラーで失敗する

    *メッセージ18456、レベル14、状態1、サーバーサーバーB、行1ユーザー 'NT AUTHORITY\ANONYMOUS LOGON'のログインに失敗しました。*

エラーはリンクサーバー(サーバーB)に送られます。SQLCMDを使用して、サーバーAに対してオペレーションサーバーから手動でこのコードを実行すると、正常に実行されます。 SQLエージェントサービスアカウントとしてボックスにログオンしてSQLエージェントジョブを実行すると、正常に実行されます。エラーが発生するのは、SQLエージェントジョブがSQLエージェントサービスアカウント以外のユーザーによって実行されたときだけです。

私は、Kerberos、ダブルホップなどに関する非常に多くの投稿やブログ、MSDNの記事を読んで、すでに行われていることを実行するように指示しています。何が欠けていますか?

追加情報ようやくこれに戻って、いくつかの追加情報を見つけることができました。ボグダンのアドバイスを使用して、Process Explorerを実行し、最初のホップの資格情報がSQLエージェントサービスアカウントからのものであることを期待どおりに確認し、TCPが使用されています。ああ、それはすべての有用な情報です。ツールから抜け出すことができました。

私はウィンドウのアプリケーションログを調べて、マシン上のさまざまなインスタンスのログイン情報を探しましたが、Kerberosも使用されていないことに気付きました!!!代わりにNTLMが使用されています。

それが私が向かっている新しいパスです-Kerberosが設定されていて、ポートとインスタンスごとに適切なFQDN SDNが存在するのに、なぜNTLM認証が使用されているのですか?どういうわけか、cmdファイルまたはSQLCMD呼び出しで認証タイプを指定する必要がありますか?または、私が考えていない誤った設定がありますか?

The Mystery Deepens SQLCMD呼び出しは、エイリアスを介して「ファーストホップ」サーバーを参照しました。 SQLCMDサーバー参照を実際の名前付きインスタンスに変更し、ジョブを再実行しました。出来た!マシンとSQLインスタンスにもcNamesを使用しているので、それを使用してみました。それもうまくいきました!にやにや笑いのために、私はエイリアスを再試行しました...それはうまくいきましたか???私はこれらのそれぞれのWindowsアプリケーションログを確認しに行き、それでもNTLMとして認証を報告しています!

この時点で私は完全に困惑し、この動作を説明して残りの環境を修正する方法について途方に暮れています。

4

最後にこれを理解しました!

私たちは、非常にアクティブなSQL Serverとインスタンスの多くをSQLエイリアスと正規名で参照しています。これにより、コードを中断することなく、並列アップグレードを実行したり、マシンを切り替えたりできます。 SQLエイリアスはすべて、同じ理由で正規名を参照するように構成されています。登録した標準SPNはマシン名用です。

[〜#〜] example [〜#〜]ポート12345でリッスンしているSQL Server SSxyz\xyzInstanceがSPNを登録しました:

  • MSSQLSVC/SSxyz.mydomain.com:12345
  • MSSQLSVC/SSxyz:12345
  • MSSQLSVC/SSxyz:xyzInstance

これらはすべて、そのマシンでMSSQLSVCを所有するサービスアカウントに登録されており、資格情報を渡すように委任が設定されています。

サーバーとインスタンスの正規名もcxyz\xyzInstanceです。最後に、SQL Serverには、正規名cxyz\xyzInstanceを指すxyzAliasの32ビットと64ビットのエイリアスがあります。

ローカルPCからxyzAliasからabcAliasへのダブルホップシナリオ中に、エイリアスとSPNを解決できないため、Kerberos認証が失敗し、NTLMにフォールバックします。これが、ログがNTLMを示していた理由です。

修正は、サーバーの正規名を実際の名前に登録するためにいくつかのSPNを追加することでした。次に、SQLサービスが別のSPNに登録されます。このような:

  • setspn -sホスト/ cxyz SSxyz
  • setspn -s Host/cxyz.mydomain.com SSxyz
  • setspn -s MSSQLSVC/cxyz:12345 sqlserviceaccountname
  • setspn -s MSSQLSVC/cxyz:xyzInstance sqlserviceaccountname

登録すると、各SPNが委任用に構成されます。これらは一意のSPNとして表示され、SQLエイリアスが実際のマシン名に解決されるようにします。ログに記録されるダブルホップ認証はケルベロスであり、誰もが満足しています! ADの人を除いて...彼らは数時間で登録するSPNをたくさん持っているでしょう。

3

Xcopy Process Explorer オペレーションサーバー上。

SQL Serverエージェントによって呼び出されたCMDファイルを変更して、timeout 600失敗したsqlcmd.exe呼び出しの直前。これにより、sqlcmdが実際に呼び出される直前に10分の遅延が発生します。

ジョブが実行されることを確認します。プロセスエクスプローラーに移動し、対応するcmd.exeプロセスのプロパティタブを調べます(timeout.exeを呼び出すプロセスになります)。 [セキュリティ]タブのスクリーンショットを撮ると、長持ちします。

失敗したことがわかっているジョブを実行します。 [セキュリティ]タブを確認して、前のケースと比較してください。

Sqlcmd.exeによって使用されるセキュリティコンテキストは、SQLAGENT.EXEによって作成されるcmd.exeから継承されたものです。 2つのケースで作成されたセキュリティコンテキストの違いに気づくはずであり、それが解決策につながります。

0
bogdan