Bagaimana cara mengelola PRIVILEGES DEFAULT untuk PENGGUNA pada DATABASE vs SCHEMA?

48

Saya ingin memigrasi aplikasi berbasis database yang cukup sederhana, internal, dari SQLite3 ke PostgreSQL 9.3 dan memperketat izin dalam DB saat saya pergi.

Aplikasi saat ini terdiri dari perintah untuk memperbarui data; dan satu untuk menanyakannya. Secara alami, saya juga perlu memelihara database dengan cara lain (membuat tabel baru, tampilan, pemicu, dll).

Meskipun aplikasi ini akan menjadi satu-satunya yang di-host di server pada awalnya, saya lebih suka untuk memanggang dengan asumsi bahwa itu mungkin di-host di server dengan database lain di masa depan, daripada harus berebut nanti jika itu diperlukan di masa depan.

Saya akan berpikir bahwa ini akan menjadi seperangkat persyaratan yang cukup umum, tetapi saya mengalami kesulitan menemukan tutorial sederhana yang menjelaskan cara mengatur database baru di PostgreSQL, dengan pemisahan pengguna / hak istimewa semacam ini. Referensi panjang lebar tentang grup, pengguna, peran, database, skema, dan domain; tetapi saya menemukan mereka membingungkan.

Inilah yang saya coba sejauh ini (dari dalam psqlsebagai 'postgres'):

CREATE DATABASE hostdb;
REVOKE ALL ON DATABASE hostdb FROM public;
\connect hostdb
CREATE SCHEMA hostdb;
CREATE USER hostdb_admin WITH PASSWORD 'youwish';
CREATE USER hostdb_mgr   WITH PASSWORD 'youwish2';
CREATE USER hostdb_usr WITH PASSWORD 'youwish3';

GRANT ALL PRIVILEGES ON DATABASE hostdb TO hostdb_admin;
GRANT CONNECT ON DATABASE hostdb TO hostdb_mgr, hostdb_usr;
ALTER DEFAULT PRIVILEGES IN SCHEMA hostdb GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO hostdb_mgr;
ALTER DEFAULT PRIVILEGES IN SCHEMA hostdb GRANT SELECT ON TABLES TO hostdb_usr;

Tapi saya tidak mendapatkan semantik yang dimaksud. Saya ingin mengkonfigurasinya sehingga hanya hostdb_adminbisa membuat (dan menjatuhkan dan mengubah) tabel; yang hostdb_mgrdapat membaca, memasukkan, update dan menghapus pada semua tabel secara default; dan hostdb_usrhanya bisa membaca semua tabel (dan tampilan).

Ketika saya mencoba ini, saya menemukan bahwa saya dapat membuat tabel hostdbsebagai salah satu dari pengguna ini; tetapi, untuk setiap pengguna, saya hanya bisa membaca atau memodifikasi tabel yang dibuat oleh pengguna itu - kecuali saya menggunakan eksplisit GRANT.

Saya menduga ada sesuatu yang hilang di antara CREATE DATABASEdan CREATE SCHEMA, sesuatu untuk diterapkan SCHEMApada DATABASE?

(Ketika segalanya menjadi lebih maju, saya juga akan memiliki pertanyaan untuk menerapkan pembatasan serupa pada TRIGGERS, prosedur yang tersimpan, VIEWSdan mungkin objek lainnya).

Di mana saya dapat menemukan panduan, tutorial, atau seri video yang layak tentang ini?

Jim Dennis
sumber
2
Saya pikir (setidaknya sebagian dari) masalah Anda terletak pada publicpseudorole. Dapat dianggap sebagai peran yang setiap peran lainnya (pengguna, grup - semuanya sama) adalah anggota. Cobalah untuk menghapus hak istimewa darinya dengan, misalnya REVOKE CREATE ON SCHEMA hostdb FROM public,. Mencabut hak di tingkat basis data, seperti yang Anda lakukan, hanya menonaktifkan beberapa izin tingkat basis data, tidak berpengaruh pada skema atau tabel.
dezso
@dezso: Mungkin ada kesalahpahaman tentang hak default untuk skema. Hanya skema default yang publicterjadi bersama yang memiliki hak istimewa PUBLIC. Selain itu, tidak ada hak default untuk skema baru. Jadi ini tidak mempengaruhi use case yang ditunjukkan. Lihat bab dalam jawaban saya.
Erwin Brandstetter

Jawaban:

86

Di mana saya dapat menemukan panduan, tutorial, atau seri video yang layak tentang ini?

Anda akan menemukan semuanya di manual. Tautan di bawah ini.
Memang, masalahnya tidak sepele dan kadang membingungkan. Ini resep untuk use case:

resep

Saya ingin mengkonfigurasinya sehingga hanya hostdb_adminbisa membuat (dan menjatuhkan dan mengubah) tabel;
yang hostdb_mgrdapat membaca, memasukkan, update dan menghapus pada semua tabel secara default;
dan hostdb_usrhanya bisa membaca semua tabel (dan tampilan).

Sebagai superuser postgres:

CREATE USER schma_admin WITH PASSWORD 'youwish';
-- CREATE USER schma_admin WITH PASSWORD 'youwish' CREATEDB CREATEROLE; -- see below
CREATE USER schma_mgr   WITH PASSWORD 'youwish2';
CREATE USER schma_usr   WITH PASSWORD 'youwish3';

Jika Anda menginginkan admin yang lebih kuat yang juga dapat mengelola database dan peran, tambahkan atribut peran CREATEDBdan diCREATEROLE atas.

Berikan masing-masing peran ke level yang lebih tinggi berikutnya, sehingga semua level "mewarisi" setidaknya set hak istimewa dari level yang lebih rendah berikutnya (cascading):

GRANT schma_usr TO schma_mgr;
GRANT schma_mgr TO schma_admin;

CREATE DATABASE hostdb;
REVOKE ALL ON DATABASE hostdb FROM public;  -- see notes below!

GRANT CONNECT ON DATABASE hostdb TO schma_usr;  -- others inherit

\connect hostdb  -- psql syntax

Saya menyebutkan skema schma(bukan hostdbyang akan membingungkan). Pilih nama apa saja. Secara opsional, buat schma_adminpemilik skema:

CREATE SCHEMA schma AUTHORIZATION schma_admin;

SET search_path = schma;  -- see notes

ALTER ROLE schma_admin IN DATABASE hostdb SET search_path = schma; -- not inherited
ALTER ROLE schma_mgr   IN DATABASE hostdb SET search_path = schma;
ALTER ROLE schma_usr   IN DATABASE hostdb SET search_path = schma;

GRANT USAGE  ON SCHEMA schma TO schma_usr;
GRANT CREATE ON SCHEMA schma TO schma_admin;

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT SELECT                           ON TABLES TO schma_usr;  -- only read

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT INSERT, UPDATE, DELETE, TRUNCATE ON TABLES TO schma_mgr;  -- + write, TRUNCATE optional

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO schma_mgr;  -- SELECT, UPDATE are optional 

Untuk and drop and altermelihat catatan di bawah.

Ketika segalanya menjadi lebih maju, saya juga akan memiliki pertanyaan untuk menerapkan pembatasan serupa pada TRIGGERS, prosedur yang tersimpan, VIEWSdan mungkin objek lainnya.

Tampilan spesial. Untuk satu:

... (tetapi perhatikan bahwa ALL TABLESini termasuk pandangan dan tabel asing).

Dan untuk Tampilan yang Dapat Diupdate :

Perhatikan bahwa pengguna yang melakukan penyisipan, memperbarui atau menghapus pada tampilan harus memiliki hak menyisipkan, memperbarui atau menghapus hak istimewa pada tampilan tersebut. Selain itu pemilik tampilan harus memiliki hak istimewa yang relevan pada hubungan dasar yang mendasarinya, tetapi pengguna yang melakukan pembaruan tidak memerlukan izin apa pun pada hubungan dasar yang mendasarinya (lihat Bagian 38.5 ).

Pemicu juga istimewa. Anda membutuhkan TRIGGERhak istimewa di atas meja, dan:

Tapi kami sudah terlalu memperluas cakupan pertanyaan ini ...

Catatan penting

Kepemilikan

Jika Anda ingin mengizinkan schma_admin(sendiri) untuk menjatuhkan dan mengubah tabel, buat peran milik semua objek. Dokumentasi:

Hak untuk menjatuhkan suatu objek, atau untuk mengubah definisinya dengan cara apa pun, tidak diperlakukan sebagai hak istimewa yang dapat diberikan; itu melekat pada pemilik, dan tidak dapat diberikan atau dicabut. (Namun, efek serupa dapat diperoleh dengan memberikan atau mencabut keanggotaan dalam peran yang memiliki objek; lihat di bawah.) Pemilik secara implisit juga memiliki semua opsi hibah untuk objek tersebut.

ALTER TABLE some_tbl OWNER TO schma_admin;

Atau buat semua objek dengan peranschma_adminuntuk memulai, maka Anda tidak perlu mengatur pemilik secara eksplisit. Ini juga menyederhanakan hak default, yang kemudian Anda hanya perlu mengatur untuk satu peran:

Objek yang sudah ada sebelumnya

Hak istimewa default hanya berlaku untuk objek yang baru dibuat dan hanya untuk peran tertentu yang dibuat dengannya. Anda juga ingin menyesuaikan izin untuk objek yang ada :

Hal yang sama berlaku jika Anda membuat objek dengan peran yang tidak DEFAULT PRIVILEGESdisetel, seperti superuser postgres. Kepemilikan Tentukan kembali untuk schma_admindan hak set manual - atau set DEFAULT PRIVILEGESuntuk postgresjuga (sambil terhubung ke DB benar!):

ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT ...  -- etc.

Hak istimewa default

Anda kehilangan aspek penting dari ALTER DEFAULT PRIVILEGESperintah. Ini berlaku untuk peran saat ini kecuali dinyatakan sebaliknya:

Hak istimewa default hanya berlaku untuk database saat ini. Jadi Anda tidak mengacaukan dengan database lain di DB cluster. Dokumentasi:

untuk semua objek yang dibuat dalam database saat ini

Anda mungkin juga ingin menetapkan hak default untuk FUNCTIONSdan TYPES(bukan adil TABLESdan SEQUENCES), tetapi itu mungkin tidak diperlukan.

Hak istimewa default untuk PUBLIC

Hak istimewa yang diberikan PUBLICtidak sempurna dan ditaksir berlebihan oleh sebagian orang. Dokumentasi:

PostgreSQL memberikan hak default pada beberapa jenis objek PUBLIC. Tidak ada hak istimewa diberikan PUBLICsecara default pada tabel, kolom, skema, atau tablespace. Untuk tipe lain, hak default yang diberikan PUBLICadalah sebagai berikut: CONNECTdan CREATE TEMP TABLEuntuk database; EXECUTEhak istimewa untuk fungsi; dan USAGE hak istimewa untuk bahasa.

Penekanan berani saya. biasanya satu perintah di atas sudah cukup untuk mencakup semuanya:

REVOKE ALL ON DATABASE hostdb FROM public;

Secara khusus, tidak ada hak default yang diberikan PUBLICuntuk skema baru. Mungkin membingungkan bahwa skema default bernama "publik" dimulai dengan ALLhak istimewa untuk PUBLIC. Itu hanya fitur kenyamanan untuk memudahkan memulai dengan database yang baru dibuat. Itu tidak mempengaruhi skema lain dengan cara apa pun. Anda bisa mencabut hak istimewa ini di database templat template1, lalu semua database yang baru dibuat di kluster ini dimulai tanpa mereka:

\connect template1
REVOKE ALL ON SCHEMA public FROM public;

Hak istimewa TEMP

Karena kami mencabut semua hak istimewa hostdbdari PUBLIC, pengguna biasa tidak dapat membuat tabel sementara kecuali kami mengizinkannya secara eksplisit. Anda mungkin atau mungkin tidak ingin menambahkan ini:

GRANT TEMP ON DATABASE hostdb TO schma_mgr;

search_path

Jangan lupa untuk mengatur search_path. Jika Anda hanya mendapatkan satu basis data di kluster, Anda cukup menetapkan global default postgresql.conf. Lain (lebih mungkin) mengaturnya sebagai properti dari database, atau hanya untuk peran yang terlibat atau bahkan kombinasi keduanya. Detail:

Anda mungkin ingin mengaturnya schma, publicjika Anda menggunakan skema publik juga, atau bahkan (kurang mungkin) $user, schma, public...

Alternatifnya adalah dengan menggunakan skema "publik" default yang akan berfungsi dengan pengaturan default search_pathkecuali Anda mengubahnya. Ingatlah untuk mencabut hak istimewa PUBLICdalam kasus ini.

Terkait

Erwin Brandstetter
sumber
Saya sedang mencari cara menambahkan hak admin default untuk superuser yang baru dibuat, jadi saya tidak perlu memberinya hak tambahan di setiap tabel. Jika saya menemukan ini. Dan thismemang terlihat seperti instruksi untuk pesawat ruang angkasa ...
Denis Matafonov
@DenisMatafonov: Pengguna super memiliki semua hak istimewa secara otomatis. Saya sarankan Anda memulai pertanyaan baru dengan spesifik kasus Anda. Komentar bukan tempatnya. Anda selalu dapat menautkan ke pertanyaan / jawaban terkait untuk konteks.
Erwin Brandstetter
Ya, pengguna super memiliki semua akses, tetapi Anda tidak dapat menggeneralisasi hak default mereka. Akan sangat bagus untuk mengatur hak-hak default untuk peran dalam skema dan memiliki standar-standar itu berlaku untuk semua anggota peran saat mereka membuat tabel dalam skema. Misalnya, untuk mengatakan "pastikan setiap tabel yang dibuat dalam skema ini oleh siapa pun di tim teknik akan dapat dibaca oleh siapa pun di tim pelaporan." Singkatnya, saya ingin anggota dari peran pembuat-tabel mewarisi hak default itu.
kombinatoris