私はプログラマーであり、dbaではありません...私は危険なほど十分に知っています。
データベースのdb_ownerであるレガシーユーザーを使用してデータベースを継承しました。ビジネス上の理由で、既存のテーブル、スキーマなどに対するこのユーザーの権限を調整することはできませんが、いくつかの新しいテーブルが作成されており、このユーザーにそれらのSELECTアクセスのみを許可します。
GRANTに設定されているSELECTを除くすべてが拒否されるように、これらのテーブルに対するこのユーザーの権限が設定されています。
しかし、このユーザー(dbadmin)がこれらのテーブル(AccountingAudit)の1つでSELECTを実行しようとすると、次のエラーが発生します。
The SELECT permission was denied on the object 'AccountingAudit', database 'billing', schema 'dbo'.
このSQLを実行して、このテーブル/ユーザーに設定されている権限を確認します。
select object_name(major_id) as object,
user_name(grantee_principal_id) as grantee,
user_name(grantor_principal_id) as grantor,
permission_name,
state_desc
from sys.database_permissions
そして、これは私が返すものです:
AccountingAudit dbadmin dbo ALTER DENY
AccountingAudit dbadmin dbo CONTROL DENY
AccountingAudit dbadmin dbo DELETE DENY
AccountingAudit dbadmin dbo INSERT DENY
AccountingAudit dbadmin dbo REFERENCES DENY
AccountingAudit dbadmin dbo SELECT GRANT
AccountingAudit dbadmin dbo TAKE OWNERSHIP DENY
AccountingAudit dbadmin dbo UPDATE DENY
AccountingAudit dbadmin dbo VIEW DEFINITION DENY
AccountingAudit dbadmin dbo VIEW CHANGE TRACKING DENY
それは正しく機能しているようです?
私が行っているSELECT呼び出しは、SSMS内からの非常に基本的なSELECT * FROM AccountingAuditです。私は特別なsp_executesqlやそのようなことは何もしていません。
私は明示的に許可を与えようとしました:
GRANT SELECT ON [dbo].AccountingAudit TO dbadmin
これは効果がありません(なぜそうなのか、上記のクエリはすでに許可されていることを示しています!;-)
私はstackoverflow.comやその他の場所を検索しましたが、まだ試していないものは見つかりません。スキーマの設定方法と関係があるのでしょうか。 (現時点では、スキーマについてはほとんど知りません。)
何か案は?ありがとう!
ここではよくわかりませんが、手足を外に出ます。あなたの問題はDENY CONTROL
レコードにある可能性があります。 here をページの半分ほど下に表示します。
データベースのCONTROL権限を拒否すると、データベースのCONNECT権限が暗黙的に拒否されます。データベースのCONTROL権限が拒否されたプリンシパルは、そのデータベースに接続できません。
例はデータベースの場合であることを理解していますが、もう1つ段階的に説明します。テーブルのDENY CONTROL
は、all特権を拒否します。 REVOKE CONTROL
を実行してそれを取り除き、問題が解決するかどうかを確認します。
その場合は、ユーザーをデータベースロールに配置するか、テーブルに対する明示的な権限を拒否する必要があります。
ケンフィッシャーのsp_DBPermissions
ストアドプロシージャを使用して、アクセス許可を確認します。
DENY CONTROL
、DENY SELECT
、DENY INSERT
、DENY UPDATE
、DENY DELETE
に加えて、DENY REFERENCES
がテーブルに適用されていないことを確認してください。SELECT
ステートメントにテーブル値関数が含まれている場合は、テーブル値関数にEXECUTE AS OWNER
またはGRANT EXECUTE
が存在することを確認してください(DENY EXECUTE
は使用しないでください! )。これが事実である場合、SELECT権限がテーブルで拒否されたとは言わない可能性が高いため、エラーメッセージを注意深く読んでください。ユーザーがADユーザーまたはグループである場合は、次のスクリプトを使用してユーザーのlogin_token
(s)を特定します。
EXECUTE AS LOGIN = 'EXAMPLEDOMAIN\JOHN.DOE';
SELECT * FROM sys.login_token;
REVERT;
実際の実行計画を見てください。エラーがSET NOCOUNT ON;
のあるストアドプロシージャの内部にある場合、実際の実行計画は、SSMSの[メッセージ]タブを見るだけでは注意を払わないかもしれない洞察を提供します。 。
ステートメントをストアドプロシージャおよびSSMS "オブジェクトの依存関係の表示"としてコンパイルできます。また、Svetlana Golovkoが SQL Serverオブジェクトの依存関係を検索する別の方法 で概説したトリックもコンパイルできます。
SQL Serverプロファイラセキュリティイベント「監査スキーマオブジェクトアクセスイベント」と列「TextData」と「Success」を使用して、SQL Serverが権限を評価しているオブジェクトを追跡します。 -このイベントで2つの行が発行され、1つの値がSuccess = 1でもう1つの値がSuccess = 0である状況を確認しました。このシナリオで私が機能することがわかった唯一の解決策は、サーバーを再起動することです。 repadmin /syncall
を実行しても問題は解決せず、アプリケーション(および接続プール)の起動と停止も行われませんでした。
ログインの有効な権限を決定します。
-- '<domain>\<username>' is a domain user in the group you wish to test
EXECUTE AS LOGIN = '<domain>\<username>';
SELECT * FROM fn_my_permissions('Database.Schema.Table', 'OBJECT');
REVERT;
ユーザーがADユーザーまたはグループに関連付けられている場合は、repadmin /syncall
を実行して、Active Directoryで行われた変更をドメインコントローラー間で強制的に同期することを検討してください。 -誰かが2つのドメインコントローラの現在の値を比較する良い方法を知っている場合は、私に知らせてください。
システム全体のハードリブートを検討する前に、そのユーザーのアクティブな接続をすべて強制終了してみてください。その理由は、ユーザーがWindowsトークンをDCから取得するためです。これにはグループが含まれます。トークンは、ユーザーが新しいトークンを取得するまで更新されません。通常はログオフしてから再度ログオンします。 。
システムをハードリブートします。それは私のために働いています。まだ理由はまだ100%わかりません。ダウンタイムを乗り切ることができる場合にのみ、これを行ってください!トランザクションが非常に大きい場合は、このことを慎重に行ってください。