Dovecot ACL ile Paylaşılan Posta Kutularında Harf Düzeyinde Ekip İzinleri
destek@ kutusuna altı kişiye aynı IMAP parolasını dağıtmak iz sürülemez bir kaostur. Doğru çözüm parolayı değil hakkı paylaşmaktır: Dovecot ACL eklentisiyle lookup/read/write/expunge/admin düzeyinde, role göre şablonlanmış erişim. RFC 4314 hak harflerini gerçek ekip rollerine eşleyen, INDEXPVT ile per-user \Seen sorununu çözen ve tüm işletimi doveadm acl üzerinden yapan somut bir kurulum rehberi.
EvilMail Team12 Temmuz 202612 dk okuma
Sorun: tek parola, sıfır hesap verebilirlik
[email protected] kutusuna altı kişi giriyor. Hepsi aynı IMAP parolasını kullanıyor, çünkü kutu bir "grup adresi" ve kimse ayrı ayrı hesap açmayı düşünmemiş. Bir sabah müşteri sözleşmesini onaylayan mail kayboluyor. Log'a bakıyorsunuz, tek gördüğünüz şu:
imap(dest64): Expunged 1 msgs (UIDs 5842)
Kimin sildiğini söylemenin yolu yok. Aynı kullanıcı, aynı IP havuzu, aynı oturum. Bu, ortak parolanın kaçınılmaz sonucudur ve üç somut zarar üretir:
İz sürülemezlik. Her eylem tek bir sistem kullanıcısı adına loglanır. "Kim yaptı?" sorusunun teknik bir cevabı yoktur.
Rotasyon maliyeti. Parolayı değiştirmek istediğinizde altı istemciyi tek tek güncellemeniz gerekir; biri unutulur, o kişi kilitlenir, herkes eski parolaya geri döner.
Dovecot ACL: Paylaşılan Posta Kutusunda Ekip İzinleri | evilmail.pro — EvilMail Blog
Ayrılan çalışan riski. Stajyer gittiğinde parolayı bildiği için kutunun tamamı hâlâ onun elinde. Değiştirmezseniz sızıntı, değiştirirseniz beşi birden etkilenir.
Çözümün tezi tek cümle: parolayı paylaşma, hakkı paylaş. Her kullanıcı kendi hesabıyla girer, ortak kutuya Dovecot ACL ile yetkilendirilir. Stajyer okur ama silemez, ekip lideri arşivler, yönetici izinleri değiştirir. Ayrılan kişinin sadece kendi hesabı kapatılır, ortak kutu hiç dokunulmadan kalır.
acl eklentisini açmak (vfile backend)
Dovecot'ta ACL bir eklenti. Varsayılan kurulumda yüklü değil, iki yerde açmanız gerekiyor. conf.d/10-mail.conf içinde global plugin listesine ekleyin:
mail_plugins = $mail_plugins acl
Sonra conf.d/20-imap.conf içindeki protocol imap bloğuna imap_acl ekleyin. Bunu atlarsanız sunucu ACL'i uygular ama istemci (Thunderbird, Outlook) sağ tık "paylaşım" menüsünden hiçbir şey yönetemez:
vfile backend'i, her posta kutusu dizinine düz metin bir dovecot-acl dosyası yazar; ayrıca hangi kutuların başkalarına açıldığını izlemek için mail kökünde dovecot-acl-list adında bir index tutar. Per-mailbox dosyaların üstüne tüm domaine uygulanan bir taban politika istiyorsanız, acl satırına bir global dosya yolu ekleyin:
vfile:<dosya> yol biçimi per-mailbox dovecot-acl dosyalarını devre dışı bırakmaz, global dosyayı onların üstüne ekler. cache_secs=300 global dosyayı 5 dakika cache'ler ve büyük deployment'ta disk I/O'sunu düşürür. dovecot reload sonrası doğrulamayı doveadm acl debug ile yapın — ACL'in neden beklediğiniz gibi davranmadığını anlamanın en hızlı yolu budur.
11 hak harfi ve karşılık geldikleri IMAP eylemleri
Dovecot ACL'i RFC 4314'ün hak harflerini kullanır. Her harf tek bir IMAP eylem sınıfını açar veya kapatır. Ezberlemeniz gereken 11 tanesi şunlar:
l — lookup: Kutu LIST/LSUB çıktısında görünür. Bu olmadan kullanıcı kutunun var olduğunu bile bilmez.
r — read:SELECT/EXAMINE ile açma, FETCH ile içerik okuma.
s — write-seen:\Seen bayrağını yazma. Yani "okundu" işaretini değiştirme yetkisi.
w — write:\Seen ve \Deleteddışındaki tüm bayraklar ve keyword'ler (\Flagged, \Answered, etiketler).
t — write-deleted:\Deleted bayrağını koyma/kaldırma.
i — insert:APPEND ve COPY hedefi olma; kutuya mesaj ekleme.
p — post: Submission üzerinden gönderim. Dovecot bunu zorunlu kılmaz, pratikte neredeyse hiç kullanılmaz.
e — expunge:EXPUNGE; \Deleted işaretli mesajları kalıcı olarak silme.
k — create: Alt klasör oluşturma ve yeniden adlandırma.
x — delete: Klasörün kendisini silme.
a — admin:SETACL/DELETEACL; başkalarının haklarını değiştirme.
Buradaki kritik nüans, w, s ve t'nin ayrı olması. "Yazma" tek bir şey değil. Bir kullanıcı mesajları okuyabilir, cevaplayabilir (\Answered → w), ama okundu durumunu herkes için değiştiremesin isterseniz s'yi vermeyin. Silme yetkisi de iki katmanlı: t mesajı "silinecek" diye işaretler ama gerçekte silmez; asıl kalıcı silme e (expunge) ile olur. Bu ayrım, "işaretleyebilen ama geri döndürülemez şekilde yok edemeyen" rolleri tasarlamanızı sağlar.
Bir hakkı açıkça yasaklamak için - öneki kullanılır: -lookup, kullanıcının kutuyu görmesini negatif olarak engeller ve aynı identifier'ın pozitif haklarını ezer. Kutunun sahibi (owner) varsayılan olarak tüm haklara sahiptir; ACL'de ayrı bir owner girdisi yazmadıkça sahibin hakları kısıtlanmaz.
Role göre izin şablonları
Harfleri tek tek düşünmek yerine dört gerçek rolü sabit harf setlerine eşleyin. doveadm acl set komutunda harflerin uzun adlarını yazabilirsiniz, bu okunabilirliği ciddi artırır.
Roller kümülatif büyür: her üst rol alttakinin tüm haklarına sahiptir, üzerine yenilerini ekler. Aşağıdaki matris, hangi rolün hangi harfleri taşıdığını ve neden write ile write-seen'in ayrı sütunlar olduğunu tek bakışta gösterir.
Kullanıcılar arası paylaşılan namespace
Şimdiye kadarki komutlar, ortak kutunun INBOX'ına doğrudan ACL yazdı. Ama ekip üyelerinin bu kutuyu kendi istemcilerinde görebilmesi için Dovecot'a "paylaşılan namespace" tanımlamanız gerekiyor. Ortak kutu ayrı bir sistem kullanıcısıdır ([email protected]), diğerleri onu shared/ öneki altında görür:
namespace {
type = shared
separator = /
prefix = shared/%%u/
location = maildir:%%h/Maildir:INDEX=~/Maildir/shared/%%u:INDEXPVT=~/Maildir/shared/%%u
subscriptions = no
list = children
}
Buradaki %%u, paylaşan kullanıcının adresine açılır; [email protected] istemcisinde kutu shared/[email protected]/INBOX olarak belirir. acl_shared_dict, "kim kutusunu kime paylaştı" eşleşmesini tutar; bu sözlük olmadan namespace boş görünür.
En sık yapılan hata burada gizli.INDEXPVT parametresini atlarsanız, tüm kullanıcılar aynı \Seen index'ini paylaşır: bir kişi bir maili açtığında herkeste "okundu" görünür, bir başkası okunmamışa çevirdiğinde bu da herkese yansır. INDEXPVT, her kullanıcının kişisel okundu durumunu kendi ev dizinindeki ayrı bir index'te tutar — paylaşılan bir kutuda tam olarak istediğiniz davranış budur. Aşağıdaki diyagram çözümleme akışını gösteriyor.
subscriptions = no ile list = children birlikte, kullanıcının paylaşılan kutunun alt klasörlerini ayrıca abone olmadan görmesini sağlar. Namespace veya plugin değişikliği yaptığınızda dovecot reload gerekir; sadece ACL girdisi değiştirmek restart istemez.
doveadm acl ile günlük işletim
Kurulum bittikten sonra tüm işletim doveadm acl alt komutlarından yürür. Mevcut girdileri listelemek:
Bu, lookup hakkının olup olmadığından acl_shared_dict girdisinin var olup olmadığına, index'in erişilebilirliğine kadar tüm çözümleme zincirini adım adım yazdırır. dovecot-acl-list index'i bozulur veya güncel kalmazsa doveadm acl recalc -u [email protected] ile yeniden inşa edin.
Kritik uyarı: ACL alt klasörlere miras kalmaz.INBOX'a hak verdiğinizde INBOX/Arşiv etkilenmez; her posta kutusu kendi dovecot-acl dosyasını taşır. Tüm ağaca aynı politikayı uygulamak için döngü kurun:
On kişilik bir destek ekibine tek tek user= satırı yazmak sürdürülemez. Bunun yerine kullanıcıya bir grup etiketi yapıştırın. passdb/userdb extra field olarak:
acl_groups=support,billing
Artık ACL'de bireyler yerine grup tanımlayabilirsiniz. ACL identifier'larınız şunlar: user=, group=support, group-override=support, owner, authenticated, anyone.
group= ile group-override= arasındaki fark inceliklidir ama önemlidir. Öncelik sırası şudur: group-override > user > owner > group > authenticated > anyone. Yani bir kullanıcıya user=x -expunge ile expunge'ı özel olarak yasakladıysanız, normal group= bunu geri veremez — çünkü user= girdisi grubu ezer. Ama group-override=support expunge, bireysel negatif hakkı da ezerek expunge'ı geri açar. Override'ı, "istisnaları merkezi grup politikasıyla geçersiz kılmak" (örneğin bir kullanıcıyı geçici olarak kilitlemek) için saklayın.
Taban politikayı global-acl.conf ile tüm domaine yayabilirsiniz. Global dosyanın formatı, kutu dizinindeki dovecot-acl'den bir noktada ayrılır: her satır bir mailbox deseniyle başlar, ardından identifier ve hak harfleri gelir (* tüm kutular anlamına gelir):
INDEXPVT'yi asla atlama. Yoksa \Seen tüm kullanıcılarca paylaşılır; paylaşılan kutuda en can sıkıcı ve teşhisi en zor buglardan biridir.
imap_acl protokol eklentisini ekle. Eksikse Thunderbird/Outlook'tan sağ tık ile paylaşım/ACL yönetimi çalışmaz, sadece komut satırından yönetebilirsin.
expunge'ı kimseye kolayca verme.e olmadan kullanıcı \Deleted işaretleyebilir ama kalıcı silemez; Trash klasörü + retention politikasıyla "silme" simüle edilir ve geri alınabilir kalır.
ACL miras beklentisini bırak. Her mailbox kendi dovecot-acl'ini taşır; alt klasörlere döngüyle uygula.
Doğru şeyi reload et. Namespace/plugin değişikliği dovecot reload ister; sadece ACL girdisi değişikliği istemez, anında etkilidir.
Şüphede kalınca debug.doveadm acl debug çözümleme zincirinin hangi adımında hakkın düştüğünü gösterir; log'da tahmin yürütme.
Rotasyon artık kutu değil hesap sorunu. Biri ekipten ayrıldığında sadece kendi hesabını kapat; ortak kutuya ve diğer beş kişiye hiç dokunmadan erişim kesilir.
Ortak parolayı bıraktığınız an, "kim sildi?" sorusunun cevabı log'da net bir kullanıcı adı olur, parola rotasyonu tek bir hesapla sınırlanır ve stajyerinizin bir müşteri sözleşmesini geri döndürülemez şekilde yok etme yetkisi hiç var olmaz. evilmail.pro üzerindeki paylaşılan adreslerinizi bu modelle kurun; ölçek büyüdükçe farkı doveadm acl debug çıktısının ne kadar sık işinize yaradığından anlarsınız.