Menerima "Izin SELECT ditolak pada objek" meskipun sudah diberikan

11

Saya seorang programmer, bukan dba ... Saya tahu cukup berbahaya.

Saya telah mewarisi database dengan pengguna lawas yang merupakan db_owner untuk database tersebut. Kami tidak dapat menyesuaikan izin pengguna ini untuk tabel, skema, dll yang ada, karena alasan bisnis, tetapi beberapa tabel baru sedang dibuat, dan saya hanya ingin pengguna ini memiliki akses SELECT pada mereka.

Izin telah ditetapkan untuk pengguna ini untuk tabel ini sehingga semuanya DITOLAK, kecuali SELECT, yang diatur ke GRANT.

Namun ketika pengguna ini (dbadmin) mencoba melakukan SELECT pada salah satu tabel ini (AccountingAudit), kesalahan ini terjadi:

The SELECT permission was denied on the object 'AccountingAudit', database 'billing', schema 'dbo'.

Saya sudah menjalankan SQL ini untuk mencoba dan melihat izin apa yang ditetapkan untuk tabel / pengguna ini:

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

Dan inilah yang saya dapatkan:

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

Sepertinya itu harusnya bekerja dengan baik?

Panggilan SELECT yang saya buat adalah SELECT * yang sangat mendasar dari AccountingAudit, dari dalam SSMS. Saya tidak melakukan sp_executesql khusus atau semacamnya.

Saya sudah mencoba memberikan izin secara eksplisit:

GRANT SELECT ON [dbo].AccountingAudit TO dbadmin

Ini tidak berpengaruh (mengapa, kueri di atas sudah menunjukkan itu diberikan! ;-)

Saya telah mencari melalui stackoverflow.com dan tempat lain, dan tidak dapat menemukan apa pun yang belum saya coba. Saya bertanya-tanya apakah itu ada hubungannya dengan bagaimana pengaturan skema. (Pada titik ini saya tahu sedikit tentang skema.)

Ada ide? Terima kasih!

Mason G. Zhwiti
sumber

Jawaban:

10

Saya tidak yakin di sini, tapi saya akan mengambil risiko. Saya pikir masalah Anda mungkin dengan DENY CONTROLcatatan Anda . Lihat di sini sekitar setengah jalan halaman:

Menolak izin KONTROL pada database secara implisit menolak izin CONNECT pada database. Prinsipal yang ditolak izin KONTROL pada database tidak akan dapat terhubung ke database itu.

Saya menyadari bahwa contoh adalah untuk basis data, tetapi gunakan satu tingkat lagi. A di DENY CONTROLatas meja akan menolak semua hak istimewa di atasnya, saya kira. Lakukan REVOKE CONTROLuntuk menyingkirkan itu dan lihat apakah itu memperbaiki masalah Anda.

Jika demikian, Anda harus menempatkan pengguna dalam peran basis data atau menolak mereka hak istimewa eksplisit terhadap tabel.

Thomas Stringer
sumber
1
Terima kasih! Awalnya dalam percobaan saya, saya menemukan bahwa jika CONTROL tidak ditolak, maka mereka bisa SELECT. Tetapi dalam membaca BOL saya telah salah menafsirkan ini berarti saya memberi pengguna kontrol penuh atas tabel. Saya melihat sekarang bahwa selama saya tidak menyangkal mereka KONTROL, saya masih dapat menjaga izin lainnya (INSERT, DELETE, dll) di tingkat DENY, dan mencapai tingkat izin yang saya inginkan. Terima kasih!
Mason G. Zhwiti
Ini adalah kehalusan yang saya utarakan, meskipun tidak menyelesaikan masalah saya, yang saya rasa sebagian besar akan diabaikan. Secara terpisah, saya telah menemukan jika menggunakan grup direktori aktif, jika Anda telah mengubah keanggotaan grup, repadmin / syncall tidak selalu memperbaiki masalah dan saya menemukan me-reboot server memperbaiki masalah. Namun, masih mencari pendekatan godam.
John Zabroski
0
  1. Gunakan sp_DBPermissionsprosedur tersimpan Ken Fisher untuk melihat izin.

    1. Pastikan DENY CONTROLtidak diterapkan ke meja, di samping umum DENY SELECT, DENY INSERT, DENY UPDATE, DENY DELETEdan DENY REFERENCES.
    2. Jika SELECTpernyataan berisi fungsi bernilai tabel, pastikan ada EXECUTE AS OWNERfungsi bernilai di atas meja atau fungsi GRANT EXECUTEdi atasnya (dan tidak DENY EXECUTE!). Jika ini masalahnya, baca pesan kesalahan lebih hati-hati karena sepertinya tidak akan mengatakan izin SELECT ditolak di atas meja, tetapi sebaliknya sesuatu tentang EXECUTE ditolak.
  2. Jika pengguna adalah pengguna atau grup AD, gunakan skrip berikut untuk menentukan pengguna login_token:

EXECUTE AS LOGIN = 'EXAMPLEDOMAIN\JOHN.DOE';
SELECT * FROM sys.login_token;
REVERT;
  1. Lihatlah rencana eksekusi yang sebenarnya. Jika kesalahan ada di dalam prosedur tersimpan SET NOCOUNT ON;, maka rencana eksekusi yang sebenarnya akan memberi Anda wawasan Anda mungkin tidak memperhatikan dengan hanya melihat tab Pesan di SSMS, karena "Baris yang terpengaruh" mungkin berada di luar kendali Anda.

    1. Cari pemicu atau tabel temporal.
  2. Anda dapat mengkompilasi pernyataan sebagai prosedur tersimpan dan SSMS "Lihat Ketergantungan Objek", serta trik yang diuraikan oleh Svetlana Golovko dalam Berbagai Cara untuk menemukan Ketergantungan Objek SQL Server

  3. Gunakan acara Keamanan Profiler SQL Server "Acara Akses Objek Skema Audit" dan kolom "TextData" dan "Sukses" untuk melacak objek mana SQL Server sedang mengevaluasi izin. - Saya telah melihat situasi di mana ada dua baris yang dipancarkan untuk acara ini, dan satu nilai mengatakan Sukses = 1 dan yang lainnya mengatakan Sukses = 0. Dalam skenario ini, satu-satunya solusi yang saya temukan untuk berfungsi adalah me-reboot server. Bahkan menjalankan repadmin /syncalltidak memperbaiki masalah, memulai dan menghentikan aplikasi (dan karena itu kolam koneksi).

  4. Tentukan izin efektif untuk masuk:

-- '<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;
  1. Jika pengguna terikat dengan pengguna atau grup AD, pertimbangkan repadmin /syncalluntuk memaksa perubahan apa pun yang dibuat dalam direktori aktif untuk menyinkronkan pengontrol domain Anda. - Jika seseorang mengetahui cara yang baik untuk membandingkan nilai saat ini dari dua pengontrol domain, beri tahu saya.

  2. Sebelum mempertimbangkan untuk mem-boot ulang seluruh sistem, coba matikan semua koneksi yang aktif untuk pengguna tersebut. Alasannya adalah pengguna mendapat token windows mereka dari DC yang mencakup grup mereka. Token tidak akan diperbarui sampai pengguna mendapat token baru - biasanya dengan log off dan kemudian login kembali.

  3. Hard reboot sistem. Ini berhasil untuk ku. Masih belum 100% yakin mengapa. HANYA LAKUKAN JIKA ANDA DAPAT MENYELAMATKAN WAKTU BAWAH! HATI-HATI TENTANG MELAKUKAN INI SAAT ANDA MEMILIKI TRANSAKSI YANG LUAR BIASA!

John Zabroski
sumber