PostgreSQL "permission denied for table" — Hangi Rol, Hangi Yetki Eksik?
permission denied hatasında dört yetki katmanı: şema USAGE, tablo yetkisi, sequence ve search_path. PG 15 sonrası public şema değişikliği.
Operasyonel Doğrulama & Güvenilirlik Standardı
Hata mesajı semptomdur, kök neden değildir. Sunucuyu yeniden başlatmadan veya rastgele ayar değiştirmeden önce aşağıdaki "Nedeni ayırt eden tek sorgu"yu çalıştırarak gerçek senaryoyu netleştirin.
▸Belirti
ERROR: permission denied for table siparis
ERROR: permission denied for sequence siparis_id_seq
ERROR: permission denied for schema public
ERROR: permission denied for relation siparisSQLSTATE hata kodu: 42501 (insufficient_privilege).
Dört farklı nesne türü, dört farklı yetkilendirme katmanını temsil eder. Hepsi aynı "permission denied" sözcükleriyle başladığı için çoğu mühendis hepsine rastgele GRANT ALL uygular ve güvenlik açığı yaratır veya sequence katmanını atladığı için yine başarısız olur.
PUBLIC sahte-rolünün public şeması üzerindeki varsayılan CREATE yetkisi tamamen kaldırıldı. PostgreSQL 14 ve öncesinde sorunsuz çalışan migration scriptleri, PostgreSQL 15'e geçildiğinde aniden permission denied for schema public hatası verir. Bu sayfanın en sık ziyaret edilme sebebi bu mimari değişikliktir.▸Nedenini Doğrulayan Teşhis Sorguları
Önce havuzlayıcı veya ORM oturumunun sizi gerçekte hangi kimlikle bağladığını görün:
SELECT current_user, session_user, current_setting('search_path');Ardından yetkileri tek tek katalog tablolarından aramak yerine PostgreSQL'in yerleşik doğrulama fonksiyonlarıyla sorgulayın:
SELECT has_schema_privilege('app_user', 'public', 'USAGE') AS sema_usage,
has_table_privilege('app_user', 'public.siparis', 'SELECT') AS tablo_select,
has_table_privilege('app_user', 'public.siparis', 'INSERT') AS tablo_insert,
has_table_privilege('app_user', 'public.siparis', 'UPDATE') AS tablo_update,
has_sequence_privilege('app_user', 'public.siparis_id_seq', 'USAGE') AS seq_usage;Hangi sütun false dönüyorsa eksik olan yetki katmanı odur. Bu tek sorgu deneme-yanılma turlarını anında bitirir.
▸Dört Yetki Katmanı ve Kritik Tuzaklar
1. Şema USAGE Yetkisi
Şema üzerinde USAGE yetkisi olmadan içindeki hiçbir tabloya veya fonksiyona erişilemez. Tabloda GRANT ALL verilmiş olsa dahi şema USAGE eksikse bu hata patlar:
GRANT USAGE ON SCHEMA public TO app_user;2. Tablo DML Yetkisi
SELECT, INSERT, UPDATE, DELETE. Tuzak: Bir tabloda UPDATE çalıştırabilmek için WHERE koşulundaki kolonları okumak gerekir; dolayısıyla yalnızca UPDATE verip SELECT vermemek pratik dünyada sorgunun reddedilmesine neden olur.
3. Sequence (Dizi) Yetkisi — En Çok Unutulan Katman!
Tablonuzda serial veya GENERATED BY DEFAULT AS IDENTITY kolonu varsa, yeni bir satır eklemek (INSERT) yalnızca tablo yetkisiyle tamamlanamaz; arka plandaki sequence nesnesinde de USAGE, SELECT yetkisi gerekir:
GRANT USAGE, SELECT ON SEQUENCE public.siparis_id_seq TO app_user;4. search_path Çözümleme Tuzağı
Eğer veritabanınızda birden fazla şemada (public.siparis ve muhasebe.siparis) aynı isimli tablolar varsa, PostgreSQL nesneyi search_path sırasına göre çözümler:
SELECT to_regclass('siparis');Eğer sorgu sizin yetkili olduğunuz tabloya değil, search_path içinde daha önde yer alan yetkisiz olduğunuz diğer şemadaki tabloya çözümleniyorsa sorun yetki değil arama yoludur.
▸Adım Adım Kalıcı Çözüm
1. En Az Yetki Prensibiyle Açıkça Yetki Verin
GRANT USAGE ON SCHEMA public TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.siparis TO app_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_user;2. Gelecekte Oluşturulacak Tabloları Unutmayın!
Bugün verilen yetkiler yarın migration çalıştırılıp oluşturulan yeni tabloları kapsamaz. Bu durum, "dün gece deploy ettik, sabah sistem permission denied verdi" vakalarının ana sebebidir:
ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO app_user;FOR ROLE app_owner ifadesi son derece kritiktir. Varsayılan yetkiler yalnızca o rol tarafından oluşturulan nesneler için geçerli olur. Migration scriptleriniz süperkullanıcı (postgres) ile çalışıyorsa, FOR ROLE postgres tanımlanmadığı sürece bu kural işlemez!3. Sahip (Owner) ile Uygulama Kullanıcısını Ayırın
Veritabanı nesnelerinin sahibi DDL çalıştıran app_owner, uygulamanın bağlandığı kullanıcı ise yalnızca DML çalıştıran app_user olmalıdır. Bu ayrım, yazılımdaki bir SQL injection açığında uygulamanın DROP TABLE çalıştırmasını yapısal olarak imkansız kılar.
▸İlgili Hata Rehberleri & Hub Bağlantıları
- •SQL Server Msg 229 Permission Denied (H-39) — Bu hatanın SQL Server karşılığı (kardeş sayfa)
- •SQL Server Cannot Open Database (H-15) — Veritabanı düzeyinde erişim engeli
- •PostgreSQL Hub — PostgreSQL mimari standartları ve güvenlik runbook'ları
Diğer Veritabanı Hata Teşhisleri
Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.
PostgreSQL Bağlantı Tükenmesi ve too many clients Teşhisi
FATAL: sorry, too many clients already ve remaining connection slots hatalarının üç temel kök nedeni, yetki sınırlarıyla salt okunur pg_stat_activity teşhisi ve kalıcı iki katmanlı havuzlama çözümü.
PostgreSQL password authentication failed Hatası: Neden ve Çözüm
psql password authentication failed hatasının dört nedeni: yanlış şifre, md5/SCRAM uyuşmazlığı, pg_hba.conf sırası ve yanlış cluster. Adım adım teşhis.
PostgreSQL connection refused: 8 Adımda Kesin Teşhis
Connection refused, timeout ve "no pg_hba.conf entry" arasındaki fark; listen_addresses, port, firewall ve Docker port yayınlama kontrolleri.