web-dev-qa-db-ja.com

モジュールの署名とSSISカタログの内部手順に関する問題

SSISパッケージを実行するストアドプロシージャを設定しようとしています。ユーザーがこのストアドプロシージャのみを実行できるようにしたいので、別のユーザーとして実行する必要があります。

私は この記事 を見つけました。これは、証明書を作成し、特権ログインが実行できるようにモジュールに署名することを詳述しています。

ログインを偽装したコマンドを実行しようとすると、次のエラーが表示されます。

プリンシパル「CrossDbCertLogin」が存在しないか、このタイプのプリンシパルを偽装できないか、権限がないため、サーバープリンシパルとして実行できません。

問題を再現するスクリプトは次のとおりです。

create certificate CrossDatabaseCert
ENCRYPTION BY PASSWORD = 'passA'
WITH SUBJECT = 'Certificate for Cross-Database Database Impersonation'
GO


CREATE Login CrossDbCertLogin FROM CERTIFICATE CrossDatabaseCert
GO

backup certificate CrossDatabaseCErt to file='C:\temp\CrossDatabaseCert.CER'
WITH PRIVATE KEY
(
    FILE = 'C:\temp\CrossDatabaseCert.PVK',
    DECRYPTION BY PASSWORD = 'passA',
    ENCRYPTION BY PASSWORD = 'passB'
)
go

use msdb
create certificate CrossDatabaseCert from file='C:\temp\CrossDatabaseCert.CER'
WITH PRIVATE KEY
(    FILE = 'C:\temp\CrossDatabaseCert.PVK',
    DECRYPTION BY PASSWORD = 'passB',
    ENCRYPTION BY PASSWORD = 'passA'
)
Go

EXECUTE AS LOGIN=N'CrossDbCertLogin';
SELECT 1

最終的には証明書をストアドプロシージャに追加しますが、なりすましが機能していないようなので、最初にそれを機能させようとしています。

何が悪いのですか?

編集:私の手順のもう少し情報。

「EXECUTE AS OWNER」に変更すると(以下の例と同じ形式)、次のエラーが表示されます。

メッセージ27123、レベル16、状態1、プロシージャcreate_execution、行39操作は、SQL Server認証を使用するアカウントでは開始できません。 Windows認証を使用するアカウントで操作を開始します。

メッセージ27123、レベル16、状態1、プロシージャset_execution_parameter_value、行34操作は、SQL Server認証を使用するアカウントでは開始できません。 Windows認証を使用するアカウントで操作を開始します。

メッセージ27123、レベル16、状態1、プロシージャstart_execution、32行目SQL Server認証を使用するアカウントでは操作を開始できません。 Windows認証を使用するアカウントで操作を開始します。

プロシージャ内で、3つの内部SSISカタログプロシージャCreate_ExecutionSet_Execution_Parameter_Value、およびStart_Executionを呼び出します。

SQLエージェントサービスアカウントとして実行するように手順を変更すると、次のエラーが発生します。

メッセージ15199、レベル16、状態1、プロシージャprepare_execution、行34現在のセキュリティコンテキストを元に戻すことはできません。 「実行」が呼び出された元のデータベースに切り替えて、再試行してください。

EDIT2:私はSQLCLR SProcを使用して元のプロシージャを呼び出し、すべての問題を解決しました。

2
Mansfield

偽装を中心に展開する2つの考え:

  1. 問題の説明とエラーメッセージから、それらはすべて、偽装/ EXECUTE ASの試行に関連するエラーを処理します。この実行コンテキストを切り替えようとする試みが全体の問題である可能性があります。なぜEXECUTE AS LOGIN = N'CrossDbCertLogin'を使用しているのですか?そのログイン(および関連する証明書など)は、直接実行するものではなく、暗黙の権限を取得するためのプロキシとして存在します。 sqlxdetails.comから従った例をさらに詳しく見てみると、EXECUTE AS LOGIN = N'HighPrivCertLogin'への呼び出しがないことがわかります。

    したがって、私は次のことから始めます。

    1. EXECUTE AS LOGIN = N'CrossDbCertLogin'へのこれ以上の試みはありません
    2. 3つのSSISカタログプロシージャを呼び出すストアドプロシージャには、noEXECUTE ASまたはEXECUTE AS CALLER(ない場合のデフォルト)のいずれかが必要です指定)
    3. [SSISDB]データベース内の証明書ベースのユーザーに、各SSISストアドプロシージャの実行権限を付与します。これらは、doesが必要なアクセス許可を持っているユーザーにマップする証明書で署名されているproc間のリンクから制限付きログインが取得する暗黙のアクセス許可です。

      USE [SSISDB];
      GRANT EXECUTE ON [Create_Execution] TO [CrossDbCertUser];
      GRANT EXECUTE ON [Set_Execution_Parameter_Value] TO [CrossDbCertUser];
      GRANT EXECUTE ON [Start_Execution] TO [CrossDbCertUser];
      

      もちろん、サンプルコードでは、[msdb]または[SSISDB]でのローカルデータベースユーザーの作成を示していませんが、これらのユーザーが作成されたと想定しています。そうでない場合は、少なくとも[SSISDB]にユーザーを作成する必要があります。これは、データベースレベルの権限が必要なためです(つまり、3つのSSISプロシージャを実行するため)。しかし、[msdb]に証明書ベースのユーザーを作成することも、おそらく害はありませんでした。

  2. 何らかの理由で(おそらく外部プロセスであるSSISが偽装認証トークンを使用できない場合)、実行コンテキスト自体に両方の特権を与える必要がありますand偽装可能(はい、これは完全にWordです。 -)、それからあなたがしようとしているので現在のアプローチは機能しません:

    • 実行コンテキストを持つことができない偽装ログイン(つまり、証明書ベースおよび非対称キーベースのログイン)
    • 元に戻すことができないEXECUTE AS句のCREATE PROCEDURE句を使用して偽装します(誰が元に戻そうとするのかはわかりませんが、これを実行しようとすると表示されるエラーメッセージです)。

    したがって、ここで2つのことを試してみてください(ここでも、上記のオプション#1ではうまくいかないと仮定しています)。

    1. "trusted_connection = true;"の接続文字列を介して接続するだけのSQLCLRストアドプロシージャを作成します。 (デフォルトのインスタンス、おそらく現在使用しているインスタンスに接続します)と、3つのSSISプロシージャを実行する[msdb]でストアドプロシージャを実行します。偽装を使用するように明示的にコーディングしない限り、デフォルトでは、SQL Serverプロセスを実行しているWindows/Active Directoryアカウント(つまり、サービスの「ログオン」アカウント)として外部接続を作成し、そのアカウントがこれらのSSISプロシージャを実行できる。このSQLCLRストアドプロシージャでその制限されたログインに対してGRANT EXECUTEを実行し、このストアドプロシージャが特権ログインとして新しい独立した接続を確立するため、このオプションでは証明書やログインは必要ありません。このSQLCLRプロシージャには、特権ログインとしてログインしてもセキュリティ上の脅威が発生しないという単一の目的があります。もう1つの重要な要素は、偽装されていないコンテキストによって接続が確立されているため、認証トークンcanが外部マシンに渡されることです。しかし、はい、アセンブリにはPERMISSION_SETEXTERNAL_ACCESSが必要です。これは、アセンブリに署名し、アセンブリから非対称キーを作成し、その非対称キーに基づいてログインを作成し、そのログインにEXTERNAL_ACCESS Assembly権限を付与することで実行できます。

      アセンブリ/非対称キーの手順のデータベース側で支援が必要な場合は、記事を書きました SQLCLRレベル4への階段:セキュリティ(外部およびUNSAFEアセンブリ) (無料登録が必要です)。これを行うステップバイステップの例; Visual Studioでの秘密キーの作成は表示されません。

      または

    2. 制限されたログインがINSERTへのアクセス許可を持つキューテーブルを作成します。次に、キューテーブルをチェックするSQLエージェントジョブを作成し、「新しい」レコードが見つかった場合は、ステータスを「処理中」に更新し、3つのSSISプロシージャを呼び出す[msdb]のストアドプロシージャを呼び出して、終了し、キューを更新します。 「完了」にもう一度記録します。この方法では、SQLエージェントは、偽装されていないコンテキストからの新しい接続を介してストアドプロシージャを実行しています。したがって、認証トークンcanを外部マシンに渡すことができます。

2
Solomon Rutzky

あなたが参照するVedranのコードでは、他のデータベースのストアドプロシージャにも署名しています。私はあなたがコードであなたがその最後のステップを踏んだことを見ません。

Erland Sommarskogは、この問題について http://www.sommarskog.se/grantperm.html で広範な議論を行っています。これには、彼の言葉によると、 "The Problematic EXECUTE AS"。の議論が含まれます。

SQLエージェントジョブを開始するための次のリンクでは、特定の権限を持たないログインに権限を委任するためのさらに別のアプローチを見ることができます。参照: sysadmin以外、SQL Serverエージェントジョブの非所有者に実行を許可

それが魅力的な場合は、独自のストアドプロシージャを作成して、ユーザーがSSISプロセスを開始できるようにすることができます。

2014/10/20編集:「...のため、サーバープリンシパルとして実行できません」

まず、sysadminの場合、問題はあなたの権利ではなく、実行しようとしているコンテキストです。 (私はあなたがsysadminであると信じています。)したがって、それは次のようなものである可能性があります:

  1. 使用するサーバープリンシパルがWindows Groupである場合、偽装することはできません。
  2. 最近、別のサーバーからシステムデータベース(msdbなど)を復元しましたか?その場合、msdbに表示されるアカウントは、現在のサーバーのアカウントと一致しない可能性があります。 (database_principalsには同じ名前が表示される場合がありますが、sidは異なる場合があります。)その場合は、exec sp_change_users_login 'AutoFix','principalname'を使用してみてください。
  3. データベースの所有者(master.sys.databases内)がデータベースのsidユーザーと同じdboでない場合、偽装することはできません。 (msdbsaの通常の所有者であるため、これはmsdbでは起こりそうにありません。)
  4. ログインが削除された場合、ユーザーがデータベースに残っていても、アカウントを偽装できない可能性があります。

そして、おそらく他のフレーバーもあります。

3
RLF