web-dev-qa-db-ja.com

トリガーによって実行される関数の更新または選択を許可しない権限

同じSQL Server 2014インスタンス上に2つのデータベースAとBを使用して、以下を実行しようとする一連のスクリプトを記述しました(非常に高レベルの疑似コードで記述)。

  1. ユーザー更新テーブルA.dbo.Main

  2. A.dbo.Mainには、ストアドプロシージャを呼び出すUPDATE, DELETE, INSERTに対するトリガーがありますA.CallProcInB

  3. A.CallProcInB次に、B.RunComponentsUpdateというBのストアドプロシージャを呼び出します。

  4. 次に、B.RunComponentsUpdateは、ビューとB.dbo.A_ViewおよびB.dbo.B_Tableというテーブルをマージします。

問題は、SQL Server 2014 Expressを実行しているパーソナルコンピューターでこれらの一連のスクリプトを完全に機能させることです。データベースAとBのスキーマ設定はまったく同じですが、SQL Serverを実行している会社のメインサーバーにすべてをセットアップすると、 2014次のエラーメッセージが表示されます。

System.Data.Odbc.OdbcException(0x80131937):
エラー[42000] [Microsoft] [ODBC SQL Serverドライバー] [SQL Server]
オブジェクト 'B_Table'、データベース 'B'、スキーマ 'dbo'に対するSELECT権限が拒否されました。エラー[42000] [Microsoft] [ODBC SQL Server Driver] [SQL Server]
オブジェクト 'B_Table'、データベース 'B'、スキーマ 'dbo'に対するUPDATE権限が拒否されました。

これで私のパーソナルコンピュータサーバーの問題を修正するには十分だったので、AとBの両方ですべての特権を初期トリガーをアクティブにするユーザーに与えようとしました。ただし、基本的に「神」の特権を与えるだけでは、サーバーでこのエラーを解決するのに十分ではありません。

3
ErickM

このソリューションは予想よりもはるかに単純であることがわかりました。最初にトリガーをアクティブにする特定のユーザーがいること、およびそのユーザーに「神」の特権を与えたと述べました。

結局のところ、私の経験から、そのユーザーにdb_denywriteおよびdb_denyread、それらを実際にユーザーにBへの読み取りまたは書き込みからdeny他のユーザーに権限を与える特権であると考えました。

ただし、これらの「許可」によって実際に私の神のユーザーがBへの読み取りまたは書き込みを拒否したため、これはケースの逆です。ボックスをオフにすると、すべてが機能します。

2
ErickM

データベース間の所有権の連鎖やTRUSTWORTHYが有効になっておらず、sa ;-)としてログインしていない場合は、権限エラーが予想されます。

これは、DBA.SEの別の質問に対する私の回答で説明されている(そして解決されている)問題と非常に似ています。

クロスデータベース証明書を使用する場合のトリガーの権限

ただし、その場合、データベースBにトリガーがあり、それはここの状況ではありません。それでも、これはかなり簡単に解決できるはずであり、他の回答で説明されているものと同様の設定を使用します。

特定の問題に必要な手順は次のとおりです(すべて他の回答に示されています)。

  1. データベースAに証明書を作成します。
  2. その証明書を使用してA.dbo.CallProcInBストアドプロシージャに署名します。
  3. 証明書をファイルまたは一時テーブル(リンクされた回答に示されているように)にバックアップします。

  4. 同じ証明書をデータベースBに作成します(リンクされた回答に示されているように、バックアップファイルから取得するか、一時テーブルから取得します)。
  5. その証明書からユーザーを作成します。
  6. 新しい証明書ベースのユーザーにB.dbo.RunComponentsUpdateストアドプロシージャのEXECUTEを付与します。

それで十分です

anyA.dbo.CallProcInBストアドプロシージャへの変更により、署名が失われることに注意してください。このような場合は、もう一度ADD SIGNATUREを実行してください。

3
Solomon Rutzky