Bu makalede, Active Directory ortamında kullanıcı hesapları kilitlendiğinde, ilgili kişilere SMS/E-Posta yoluyla otomatik bildirim gönderilmesini ele alıyoruz. “Zaten bilgisayar ekranında hesap kilitli uyarısı çıkıyor, buna neden gerek var?” diye düşünebilirsiniz. Ancak, bu tür bildirimlerin önemli bazı avantajları vardır.
- Kullanıcılar bu bildirimlerde yönlendirilecekleri selfservis adresler sayesinde hesap kilidini açma veya parola sıfırlama gibi işlemleri kendileri yapabilirler. Bu, hem zaman kazandırır hem de BT ekibine olan bağımlılığı azaltır.
- 7/24 çalışan kurumlarda, mesai saatleri dışında yaşanan hesap kilitlenmelerinde kullanıcı hesabının ne zaman açılacağını bilemez. Bu da gereksiz destek taleplerine neden olabilir. Oysa kullanıcıya “Hesabınız 5 dakika içinde açılacak” gibi bir bilgi verilirse süreç daha rahat yönetilebilir.
- Farklı uygulamalarda LDAP kimlik doğrulaması kullanıldığında, hesap kilitlense bile bu durum kullanıcıya doğrudan yansıtılmaz. Bu nedenle kullanıcı sorunun ne olduğunu anlayamaz ve yine teknik destek ister.
Bu gibi nedenlerle, kullanıcıya otomatik bildirim göndermek sadece bilgi vermek için değil, aynı zamanda BT ekiplerinin iş yükünü azaltmak için de önemli bir adımdır.
İlk olarak ortamda birden fazla Domain Controller olduğundan, kullanıcı hesabı kilitlendiğinde aynı olay (Event ID 4740) birden fazla DC üzerinde eş zamanlı olarak kaydedilebilir. Bu durum, aynı olayın birden fazla kez algılanmasına ve dolayısıyla kullanıcıya birden fazla bildirim (SMS/E-Posta) gönderilmesine neden olabilir.
Bu tür tekrarlayan bildirimlerin önüne geçebilmek için, tüm Domain Controller sunucularının erişebileceği ortak bir paylaşım klasörü veya dosya kullanılması önerilir. Bu ortak dosya, kilitlenme olaylarının kaydedilmesi ve daha önce aynı kullanıcıya bildirim gönderilip gönderilmediğinin kontrol edilmesi amacıyla kullanılmalıdır. Böylece aynı kullanıcıya aynı olay için yalnızca tek bir bildirim gönderilmiş olur. Bunun için aşağıdaki gibi herhangi bir Domain Controller üzerinde dosya oluşturabilirsiniz.
- \\dc-01\netlogon\logs\lockedUsers.txt
Kullanıcıların bildirim alabilmesi için, Active Directory ortamınızda aşağıdaki kullanıcı özniteliklerinin (attributes) dolu olduğundan emin olmalısınız.
- mail → Kullanıcının e-posta adresi
- telephoneNumber→ Kullanıcının SMS alabileceği cep telefonu numarası
Bu bilgiler, gönderilecek bildirimlerin doğru kişiye ulaşması için zorunludur.
Aşağıda sunulan PowerShell scripti bir not defterince açın ve .ps1 uzantılı olarak Active Directory sunucunuzda C:\Scripts\account_lock.ps1 dizinine kaydediniz.
- Script içinde değiştirilmesi gereken satırların başlarına 3 adet ### sembolü koyularak işaretlenmiştir.
Script
Add-Type -AssemblyName System.Web
### Paylasilan dosya yolunu kendi yapiniza göre düzenleyin.
$logPath = "\\dc1\NETLOGON\Logs\lockedUsers.txt"
# Dosya yoksa olustur
if (-not (Test-Path $logPath)) {
New-Item -Path $logPath -ItemType File -Force | Out-Null
}
# Dosya kilitli sekilde islem yap
$fs = [System.IO.File]::Open($logPath, 'Open', 'ReadWrite', 'None')
$reader = New-Object System.IO.StreamReader($fs)
$writer = New-Object System.IO.StreamWriter($fs)
$writer.AutoFlush = $true
try {
$today = (Get-Date).Date
$cleanedLines = @()
$lines = @()
# Dosyadaki tüm verileri oku ve sadece bugünün kayitlarini al
while (-not $reader.EndOfStream) {
$line = $reader.ReadLine()
if ($line -match ";") {
$parts = $line -split ";"
try {
$entryDate = [datetime]$parts[1]
if ($entryDate.Date -eq $today) {
$cleanedLines += $line
$lines += [PSCustomObject]@{
User = $parts[0]
Time = $entryDate
}
}
} catch {}
}
}
# Dosyayi yeniden yaz (sadece bugünün kayitlari)
$fs.SetLength(0)
foreach ($line in $cleanedLines) {
$writer.WriteLine($line)
}
# En son 1 adet 4740 event al
$event = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4740} -MaxEvents 1
$xml = [xml]$event.ToXml()
$username = $xml.Event.EventData.Data | Where-Object { $_.Name -eq "TargetUserName" } | Select-Object -ExpandProperty '#text'
$recent = $lines | Where-Object { $_.User -eq $username -and $_.Time -gt (Get-Date).AddMinutes(-1) }
if ($recent) {
Write-Host "Zaten gönderildi: $username"
} else {
$user = Get-ADUser $username -Properties telephoneNumber, mail
$recipient = $user.telephoneNumber
$email = $user.mail
### Ortak mesaj içerigini kendi yapiniza göre düzenleyin.
$message = "Sayin $username, hesabiniz cok sayida hatali parola denemesi nedeniyle gecici olarak kilitlendi. Lutfen 5 dakika sonra tekrar giris yapmayi deneyin.`n`nEger hemen erisim saglamaniz gerekiyorsa, parola.example.com adresinden hesap kilidinizi açabilir veya parolanizi sifirlayabilirsiniz."
## ---- SMS ----
if ($recipient) {
### API bilgilerini kendi yapiniza göre düzenleyin.#
$usernameApi = "xxxxx"
$userCode = "xxxxx"
$accountId = "xxxxx"
$originator = "xxxxx"
$password = "xxxxx"
# URL encode
$messageEncoded = [System.Web.HttpUtility]::UrlEncode($message)
$originatorEncoded = [System.Web.HttpUtility]::UrlEncode($originator)
### SMS web servis adresini kendi yapiniza göre düzenleyin.#
$smsUrl = "https://webservice.example.com.tr/get/sendSms.aspx?" +
"Username=$usernameApi" +
"&UserCode=$userCode" +
"&AccountId=$accountId" +
"&MessageText=$messageEncoded" +
"&Originator=$originatorEncoded" +
"&Password=$password" +
"&ReceiverList=$recipient" +
"&SendDate=" +
"&ValidityPeriod=60"
Invoke-WebRequest -Uri $smsUrl -Method Get | Out-Null
Write-Host "SMS gönderildi: $username"
}
### SMTP bilgilerini kendi yapiniza göre düzenleyin.#
if ($email) {
$smtpServer = "smtp.gmail.com"
$smtpPort = 587
$smtpUser = "exampe@gmail.com"
$smtpPass = "xxxxxx" # Gmail için uygulama sifresi kullanin
$securePass = ConvertTo-SecureString $smtpPass -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($smtpUser, $securePass)
Send-MailMessage -From $smtpUser `
-To $email `
-Subject "Hesabiniz Kilitlendi" `
-Body $message `
-SmtpServer $smtpServer `
-Port $smtpPort `
-UseSsl `
-Credential $cred
Write-Host "E-posta gönderildi: $username"
}
# Dosyaya bugünkü yeni kaydi ekle
$timestamp = (Get-Date -Format 'yyyy-MM-dd HH:mm')
$writer.WriteLine("$username;$timestamp")
}
} catch {
Write-Warning "Hata: $_"
} finally {
$writer.Dispose()
$reader.Dispose()
$fs.Dispose()
}
Script dosyalarımızı hazırlayıp tüm domain controller üzerinde C:\Scripts dizinine kaydettiğimize göre, artık geriye tek adım kaldı. Hesap kilitlenme olayı gerçekleştiğinde bu PowerShell dosyalarının otomatik olarak çalıştırılmasını sağlamak.
Bunu yapmak için, Görev Zamanlayıcı (Task Scheduler) özelliğini kullanacağız. Task Scheduler, belirli bir olay gerçekleştiğinde tanımlı bir işlemi otomatik olarak çalıştırmak için idealdir.
Task Scheduler açın ve yeni bir görev oluşturun.
Triggers sekmesi New butonuna tıklayın ve açılan pencerede On an event seçerek aşağıdaki bilgileri doldurun.
- Log → Security
- Source → Microsoft Windows security auditing
- Event ID → 4740
Actions sekmesi New butonuna tıklayın ve açılan pencerede aşağıdaki bilgileri kullanacağınız bildirim yöntemine göre doldurun.
- Program/script → powershell.exe
- Add arguments → -ExecutionPolicy Bypass -File “C:\Scripts\account_lock.ps1”
Sonuç olarak, bu makalede Active Directory ortamında kullanıcı hesaplarının kilitlenmesi durumunda, ilgili kullanıcılara otomatik olarak bildirim gönderilmesini sağlayan bir çözüm sunduk. Bu sayede hem kullanıcı deneyimi iyileştirilmiş hem de IT ekiplerinin üzerindeki yük azaltılmış oldu.
Bir sonraki makalede görüşmek üzere.
Yorum Gönder