İçeriğe geç
wedevit

8 Eylül 2026 · 8 dk okuma · yazılım

İlhan Buğra Aslan

Bu kaydı kim değiştirdi? Uygulama içi denetim izi (audit log) tasarımı


Bir müşteri arayıp "bu siparişin tutarı değişmiş, kim değiştirdi" diye sorduğunda cevabı dakikalar içinde verebiliyorsanız uygulamanızda çalışan bir denetim izi var demektir. Denetim izi (audit log), iş açısından anlamlı eylemlerin kim, ne zaman, hangi kayıt üzerinde ve hangi değerden hangi değere biçiminde, ayrı bir yere ve sonradan değiştirilemeyecek şekilde yazılmasıdır. Geliştiricinin hata ararken baktığı uygulama logundan farklıdır: okuyucusu, saklama süresi ve bütünlük gereksinimi başkadır. Sonradan eklemesi en zor bileşenlerden biri olmasının sebebi de basit; geçmişi geriye dönük üretemezsiniz.

Uygulama logu ile denetim izi aynı şey değil

Uygulama logu geliştirici içindir. Serbest metindir, gürültülüdür, günlerle ölçülen bir süre saklanır, sorun çözüldüğünde değerini kaybeder. Denetim izinin okuyucusu ise destek ekibi, iç denetim, hukuk ve çoğu zaman müşterinin kendisidir. Yapılandırılmış ve sorgulanabilir olmak zorundadır, yıllarca durur, içeriği bir tartışmada kanıt olarak kullanılır.

Ayrımı en net yapan test şudur: uygulama logunu silerseniz sistem çalışmaya devam eder ve kimse fark etmez. Denetim izini silerseniz bir anlaşmazlıkta elinizde hiçbir şey kalmaz.

Sunucu ve altyapı loglarının toplanması, SIEM ve sürekli izleme ayrı bir başlık; onu log yönetimi ve SIEM yazımızda ele almıştık. Buradaki konu uygulamanızın kendi ürettiği iş kaydı.

Bir denetim kaydının içinde ne olmalı

OWASP'ın Logging Cheat Sheet'i meseleyi dört soruya indirger: ne zaman, nerede, kim, ne. OWASP ASVS 5.0 (Mayıs 2025) aynı gereksinimi V16.2.1 maddesinde yazar: her kayıt, olayın zaman çizelgesinin ayrıntılı incelenmesine izin verecek meta veriyi taşımalı. Pratikte bu şu alanlara karşılık gelir:

  • Olay türü: order.total_updated gibi sabit ve makine okunur bir ad. Serbest cümle değil.
  • Zaman damgası: ASVS V16.2.2 tüm bileşenlerin saatinin senkron olmasını, zaman damgasının UTC ya da açık saat dilimi farkıyla yazılmasını ister.
  • Aktör: kullanıcı kimliği, aktör tipi (kullanıcı, servis hesabı, zamanlanmış iş) ve varsa adına işlem yapılan kişi. Destek ekibi müşteri hesabına girerek işlem yapabiliyorsa iki kimlik birden yazılmalı.
  • Bağlam: kaynak IP, istemci ve istek (korelasyon) kimliği.
  • Nesne: etkilenen kaydın tipi ve kimliği.
  • Sonuç: işlem gerçekleşti mi, reddedildi mi, hata mı aldı.
  • Değişiklik: değişen alanların önceki ve sonraki değeri. Tüm satırı kopyalamak yerine yalnızca farkı yazmak hem yerden kazandırır hem okumayı kolaylaştırır.
  • Gerekçe: iade sebebi, talep numarası, onay veren kişi.

Son madde en çok atlanan, sonradan en çok aranan alandır. "Fiyat 1.200'den 900'e indi" tek başına bir şey anlatmaz. "Hangi talep üzerine indi" tartışmayı bitirir.

Neyi yazmamalı

Parola, oturum jetonu, API anahtarı, kart verisi, veritabanı bağlantı dizesi ve şifreleme anahtarları denetim kaydına girmez. ASVS V16.2.5 bunu açıkça sınırlar; oturum jetonu ancak maskelenmiş ya da özeti (hash) alınmış halde yazılabilir. Hassas veriye erişimi kaydederken verinin kendisini değil, erişildiği bilgisini tutun. Anahtarların koda ve loglara sızması ayrı bir tartışma; sır yönetimi yazımızda ayrıntılandırmıştık.

Kayıtları serbest metin olarak birleştirmek de kendi riskini getirir. Kullanıcıdan gelen bir değer doğrudan satıra yazılırsa, içine satır sonu koyup sahte kayıt üretmek mümkün hale gelir. Buna log injection denir ve ASVS V16.4.1 verinin kodlanmasını ister. Kayıtları JSON gibi yapılandırılmış biçimde yazmak bu sorunun büyük kısmını ortadan kaldırır.

Denetim kayıtları çoğu zaman kişisel veri içerir; kimin okuyabileceği ve ne kadar saklanacağı bu yüzden tasarımın parçasıdır, sonraya bırakılan bir karar değil.

Hangi olaylar kaydedilir

Her veritabanı işlemini kaydetmek cazip gelir. Sonuç genellikle kimsenin açıp bakmadığı, aramanın da yavaş çalıştığı devasa bir tablodur. Daha iyi soru şu: hangi eylem bir gün tartışma konusu olur?

Başlangıç için işe yarayan liste kısadır. Kimlik doğrulama denemeleri, başarılı ve başarısız olanlar birlikte (ASVS V16.3.1). Yetki reddi ve yetki değişiklikleri (V16.3.2). Kullanıcı ekleme, çıkarma, rol atama. Parayı etkileyen her işlem: fiyat, iskonto, iade, kredi limiti. Silme ve toplu güncellemeler. Veri dışa aktarma ve rapor indirme. Yapılandırma değişiklikleri. Sözleşme, onay ve rıza kayıtları. Destek ekibinin müşteri adına yaptığı işlemler.

Yüz kalemle başlamayın. On beş kalemle başlayın, üç ay sonra gelen soruların cevaplanamayanlarına bakıp listeyi büyütün.

Kayıt nerede üretilecek: uygulama mı, veritabanı mı

Üç yaklaşım var ve üçü de tek başına eksik.

Uygulama katmanı niyeti bilir: kim, hangi ekrandan, hangi gerekçeyle yaptı. Zayıf noktası, veritabanına doğrudan bağlanıp UPDATE çalıştıran birinin arkasında iz bırakmamasıdır.

Veritabanı tetikleyicileri ve sistem sürümlü (temporal) tablolar tam tersidir: değişikliğin hepsini yakalar, ama kimin yaptığını çoğu zaman bilmez. Havuzlanmış bağlantıda gördüğü kullanıcı, uygulamanın veritabanı kullanıcısıdır. Çözümü, işlemin başında son kullanıcının kimliğini bir oturum değişkenine yazıp tetikleyicinin oradan okumasıdır. Bu tablolar SQL Server'da 2016 sürümünden beri, MariaDB'de 10.3.4'ten beri standarda yakın biçimde var. PostgreSQL çekirdeğinde yok; tetikleyiciyle ya da eklentiyle kurulur.

Üçüncüsü değişiklik yakalamadır (CDC): veritabanının kendi yazma günlüğünden satır değişikliklerini okumak. Uygulamayı yavaşlatmaz ve hiçbir değişikliği kaçırmaz, fakat aktörü ve gerekçeyi yine taşımaz.

Sahada işe yarayan bileşim şu: denetim izinin asıl kaynağı uygulama katmanı olsun, çünkü niyet orada. Veritabanı tarafındaki mekanizma da beklenmedik değişiklikleri yakalayan güvenlik ağı olarak kalsın.

Denetim kaydını iş işlemiyle aynı transaction'da yazın

Sık görülen hata, iş kaydını güncelleyip denetim kaydını sonrasında ayrı bir bağlantıdan ya da doğrudan kuyruğa atarak yazmaktır. İkisi bağımsız başarısız olabilir. Sipariş güncellenir, denetim kaydı yazılmaz; ya da tersi olur ve gerçekleşmemiş bir değişiklik kayda geçer. İkisi de sonradan güveni bozar.

Doğrusu, denetim kaydını iş verisiyle aynı veritabanı işleminin içinde yazmaktır. Kayıt başka bir sisteme gidecekse transactional outbox deseni işi çözer: aynı işlemde bir çıkış tablosuna yazarsınız, ayrı bir süreç oradan okuyup hedefe taşır. Bu desenin ayrıntısını arka plan işleri ve kuyruk yazısında anlatmıştık.

"Değiştirilemez" ne kadar değiştirilemez

ASVS V16.4.2 logların yetkisiz erişime kapalı olmasını ve değiştirilememesini, V16.4.3 ise kopyalarının uygulamadan yalıtılmış bir sisteme aktarılmasını ister. Uygulamada bunlar şu adımlara iner:

  • Uygulamanın veritabanı rolüne denetim tablosunda yalnızca INSERT yetkisi verin. UPDATE ve DELETE vermeyin.
  • Arşiv kopyasını ayrı bir hesapta, silinmeye ve üzerine yazılmaya karşı kilitli (object lock, WORM) depolamada tutun.
  • Kurcalamayı fark etmek istiyorsanız zincir kurun: her kaydın özetini hesaplarken bir önceki kaydın özetini de girdiye dahil edin. Araya kayıt sıkıştırmak ya da eskisini değiştirmek zinciri kırar.

Dürüst olmak gerekirse, tam yetkili bir veritabanı yöneticisi her şeyi değiştirebilir. Zincir ve dışarıdaki kopya bunu engellemez, fark edilmesini sağlar. Bir kaydın kanıt değeri de zaten oradan gelir.

Saat, sıra ve korelasyon

ISO/IEC 27001:2022 Ek A'da saat senkronizasyonu ayrı bir kontrol olarak durur (A.8.17). Sebebi teorik değil: olayları sıralayamıyorsanız kayıtların analiz değeri düşer, iki sistemin kaydı çakışır ve olay incelemesi tahmine döner. NTP'yi tüm sunucularda aynı kaynağa bağlayın, kayıtları UTC yazın, kullanıcıya gösterirken yerel saate çevirin.

Milisaniye çözünürlüğü bile eşitlik üretir; aynı anda yazılmış iki kaydın sırasını zaman damgasından çıkaramazsınız. Artan bir sıra numarası ekleyin. Tek bir kullanıcı eylemi birden fazla kayda dağılıyorsa hepsine aynı korelasyon kimliğini koyun. "Şu tıklama neyi tetikledi" sorusu ancak böyle cevaplanır.

Ne kadar saklanacak

Cevap, kaydın neyi kanıtladığına bağlı. Kart verisi işlenen ortamlarda PCI DSS v4 madde 10.5.1 denetim kayıtlarının en az 12 ay saklanmasını ve son üç ayın anında erişilebilir olmasını şart koşar. Ticari kayıt niteliği taşıyan işlemlerde ölçek büyür: Türk Ticaret Kanunu'nun 82. maddesi ticari defter ve belgelerin, son kaydın yapıldığı takvim yılının bitiminden itibaren on yıl saklanmasını öngörür.

On yıllık kaydı tek bir tabloda tutmak veritabanınızı yavaşlatır. Tabloyu tarihe göre bölümleyin, son üç-altı ayı çevrimiçi ve indeksli tutun, gerisini daha ucuz ve kilitli depolamaya taşıyın. Büyüyen tabloların sorgu planlarına ne yaptığını veritabanı yavaşlığı yazısında anlatmıştık.

İzi müşteriye gösterebiliyor musunuz

Kurumsal müşterilerin güvenlik soru listelerinde "kullanıcı işlemleri kayıt altına alınıyor mu, bu kayda biz erişebiliyor muyuz" maddesi neredeyse standart hale geldi. ISO 27001 belgelendirme sürecinde de aynı kayıtlar kanıt olarak isteniyor. Yani denetim izi bir noktadan sonra teknik bir detay olmaktan çıkıp satılabilir bir ürün özelliğine dönüşüyor.

Bu ekranı yaparken üç şeye dikkat edin. Birincisi, kimin hangi kaydı görebileceği bir yetkilendirme sorusudur; müşteri yöneticisi kendi kiracısının kayıtlarını görmeli, başkasınınkini değil (yetkilendirme modeli). İkincisi, filtre ve dışa aktarma olmadan ekran kullanılmaz. Üçüncüsü, iç alanları (tablo adı, hata izleri, servis kimlikleri) dışarıya sızdırmayın.

Yan fayda da var: destek ekibi "bunu kim değiştirdi" sorusunu geliştiriciye sormayı bırakır.

Nereden başlamalı

Kusursuz bir denetim altyapısı kurmaya çalışmayın, çalışan bir tane kurun. Bir anlaşmazlıkta kanıt gerektirecek on beş olayı listeleyin. Sabit şemalı tek bir tablo açın, kayıtları iş işlemiyle aynı transaction içinde yazın, uygulama rolünden UPDATE ve DELETE yetkisini alın, alanlara gerekçeyi de ekleyin. Üç ay sonra destek ekibine gelen soruları alıp o tablonun üzerinde cevaplamayı deneyin. Cevaplayamadığınız her soru, eklenmesi gereken bir alanı ya da olayı size zaten söyleyecektir.


Bu konuda yardıma mı ihtiyacınız var?

iletişime geçtüm yazılar