Active Directory Değişiklikleri için PowerShell Aracı Oluşturma
Birkaç gün önce, Active Directory etki alanınızdaki nesnelerde yapılan son değişiklikleri gösteren, daraltılabilir bölgelerle tamamlanmış, biçimlendirilmiş bir HTML raporu oluşturan, yazdığım bir PowerShell betiğini yayınladım. Active Directory RecycleBin özelliğini etkinleştirdiğiniz varsayılarak silinen nesneler dahil. Sonuçtan memnunum ve çoğunuz bunu faydalı buldunuz ve en azından bakmaya değer buldunuz. Ancak şimdi süreci geriye doğru gittiğimi fark ediyorum. Doğru, HTML oluşturma komut dosyası, Active Directory değişikliklerini göstermek için etkileşimli olarak çalıştırabileceğim PowerShell kodunu temel alıyor. Ama daha ileri gitmeliydim. Bana aynı değişiklikleri gösterecek bir PowerShell aracı oluşturmalıydım, ancak bunu bir PowerShell konsolu isteminden yapmalıydım. Bunu orijinal makalede ima etmiştim. Yazdığım komut dosyası faydalıdır, ancak yalnızca tasarlandığı şeyi yapabilir - bir HTML raporu oluşturmak. Gözetimimi şu şekilde düzelttim.
PowerShell Cmdlet'iyle başlayın
Herhangi bir PowerShell araç yapımı projesinde olduğu gibi, istediğiniz sonucu elde etmek için etkileşimli olarak çalıştırabileceğiniz bir cmdlet ve bir PowerShell ifadesi veya ifadeler kümesiyle başlamak istersiniz. Veya en azından süsleyebileceğiniz sonuçtan yeterince. Bu kodu önceki komut dosyasındaki Get-ADObject'i kullanarak elde ettim. Ancak HTML rapor komut dosyasının yalnızca tek bir şey yapabileceği yerde, komut satırı aracımın daha esnek olmasını istedim.
Credential, Server ve SearchBase gibi bazı Get-ADObject parametrelerini desteklemenin yanı sıra, kullanıcının nesnenin türünü de belirleyebilmesini istedim. Belki şu anda yalnızca Grup nesnelerini görmem gerekiyor ama yarın kullanıcıları ve bilgisayarları görmek istiyorum. Bunun gibi bir parametreye ihtiyacım olacak:
[Parameter(HelpMessage = "Specify the types of objects to query.")]
[ValidateSet("User","Group","Computer","OU")]
[ValidateNotNullOrEmpty()]
[string[]]$Category = "User",Pek çok Active Directory nesnesi türü var ancak bunlar benim düzenli olarak izlemek istediklerim. [ValidateSet()] kullanımına dikkat edin. Bunlar mümkün olan tek değerlerdir ve PowerShell bunları sekmeyle tamamlayacaktır. Doğrulama kümesine dahil edilecek bir varsayılan değer belirtirseniz bunu unutmayın.
Ayrıca hangi özellikleri görmek istediğimi de düşündüm. Orijinal nesneyle sınırlı değilsiniz. Get-ADObject komutundan istediklerimin bir listesi vardı. Ancak etki alanı denetleyicisinin adını da eklemek istedim. Etki alanı denetleyicisinin çoğaltılmasına bağlı olarak farklı sonuçlar alabilirsiniz, bu nedenle etki alanı denetleyicisini yakalamak istedim. Çıktıda bana bunu gösteren hiçbir yer bulamadım, bu yüzden her zaman kullanabileceğim bir şeye sahip olabilmek için sunucu için varsayılan bir parametre değeri ayarlamaya karar verdim.
[Parameter(HelpMessage = "Specifies the Active Directory Domain Services domain controller to query. The default is your Logon server.")]
[alias("DC")]
[ValidateNotNullorEmpty()]
[string]$Server = $env:LOGONSERVER.SubString(2)Ortam değişkeni \\DOM1 gibi bir format kullanıyor ancak Get-ADObject, DOM1'in sunucu değerini bekliyor, dolayısıyla varsayılan değerim ortam değerini ayrıştırıyor. Parametreyi zorunlu hale getirebilirdim, ancak bu aşırıya kaçmış gibi geldi. Yine de Sunucu parametresine bir ArgumentCompleter ekleyebilirdim.
[ArgumentCompleter({(Get-ADDomain).ReplicaDirectoryServers})]Küçük bir alanda bu iyi bir seçim olabilir.
LDAP Sorguları
HTML raporlama betiğim, belirli bir tarihten bu yana tüm nesnelerin değiştirilmesini sağlamak için tek bir filtre kullandı. Ancak yeni PowerShell aracım biraz daha ayrıntılı olmayı bekliyordu. Get-ADObject için işlevimdeki parametre değerlerine dayalı olarak karmaşık bir filtreleme ifadesi oluşturmaya çalışarak başladım. Bu durum çok geçmeden kontrolden çıktı. Ayrıca Active Directory'de unuttuğum bir tuhaflık vardı. İlk sürümlerim, yalnızca kullanıcıları ararken bile kullanıcılar VE bilgisayarlar için değiştirilmiş nesneleri döndürüyordu. Bunun nedeni, bilgisayar nesnesinin kullanıcı nesnesinden türetilmiş olması ve ikincisini aramanın birinciyi içermesidir.
Benim çözümüm LDAP filtrelerine geri dönmekti ki bunun iyi bir şey olduğu ortaya çıktı. Artık tam olarak aradığım nesne türünü döndüren bir filtreye sahip olabilirdim. Ancak tarihsaat değerine filtreleme eklemek başka bir kırışıklık ekledi. "WhenChanged >= '1/28/2021 14:00PM'" gibi bir şeyi ekleyemedim. Datetime değerini yyyyMMddhhmmss.ff olarak biçimlendirilmiş bir dizeye ve ardından -0400 gibi bir saat dilimi uzaklığına dönüştürmem gerekiyordu. Datetime değerini yeniden biçimlendirmek için özel bir yardımcı işlev yazdım.
Function _ConvertToLDAPTime {
#a private helper function to convert a date time object into a LDAP query-compatible value
Param([datetime]$Date)
$offset = (Get-TimeZone).baseUtcOffset
#values must be formatted with leading zeros to the specified number of decimal places
$tz = "{0:d2}{1:d2}" -f $offset.hours,$offset.Minutes
"{0:yyyyMMddhhmmss}.0{1}" -f $date,$tz
}Bu işlev kullanıcıya gösterilmediğinden ve yalnızca ana işlev içinde çağrıldığından standart olmayan bir ad kullanıyorum.
$dt = _ConvertToLDAPTime -Date $SinceBenim fonksiyonumda, bir LDAP filtresi kullanarak her nesne sınıfında döngü yapacağım.
foreach ($objClass in $Category) {
Switch ($objclass) {
"User" { $ldap = "(&(WhenChanged>=$dt)(objectclass=user)(!(objectclass=computer)))" }
"Computer" { $ldap = "(&(WhenChanged>=$dt)(objectclass=computer))"}
"Group" { $ldap = "(&(WhenChanged>=$dt)(objectclass=group))"}
"OU" { $ldap = "(&(WhenChanged>=$dt)(objectclass=organizationalunit))"}
}
Write-Verbose "[$(Get-Date)] Using LDAP filter $ldap"
$getparams["LDAPFilter"] = $ldap
Get-ADObject @getParams | Foreach-Object { $items.Add($_)}
}Yeni Nesneler Oluşturma
Sonuçlar bir liste nesnesine kaydedilir ve bu daha sonra işlenir ve ADChange tür adıyla yeni bir özel nesneye dönüştürülür.
foreach ($item in $items) {
if ($item.WhenCreated -ge $since) {
$isNew = $True
}
else {
$isNew = $false
}
#create a custom object based on each search result
[PSCustomObject]@{
PSTypeName = "ADChange"
ObjectClass = $item.ObjectClass
ObjectGuid = $item.ObjectGuid
DistinguishedName = $item.DistinguishedName
Name = $item.Name
DisplayName = $item.DisplayName
Description = $item.Description
WhenCreated = $item.WhenCreated
WhenChanged = $item.WhenChanged
IsNew = $IsNew
IsDeleted = $item.Deleted
Container = $item.distinguishedname.split(",", 2)[1]
DomainController = $Server.toUpper()
ReportDate = $ReportDate
}
} #foreach itemNeden bu çabaya girelim? Böylece nesneyi boru hattında kullanımını kolaylaştıracak şekilde özelleştirebilirim. Örneğin, birkaç takma ad özelliğinin yanı sıra bir dizi varsayılan özellik de tanımlayabilirim.
Update-TypeData -TypeName ADChange -DefaultDisplayPropertySet DistinguishedName,WhenCreated,WhenChanged,IsNew,IsDeleted,ObjectClass,ReportDate -Force
#define some alias properties for the custom object
Update-TypeData -TypeName ADChange -MemberType AliasProperty -MemberName class -Value ObjectClass -Force
Update-TypeData -TypeName ADChange -MemberType AliasProperty -MemberName DN -Value DistinguishedName -ForceAyrıca özel formatlı bir dosya da oluşturabilirim, böylece yalnızca istediğim varsayılan formatlı görünümü elde etmekle kalmaz, aynı zamanda diğer görünümleri de dahil edebilirim.
Update-FormatData $PSScriptRoot\ADchange.format.ps1xml
PowerShell çalışmamda her zaman Verbose çıktısını kullanıyorum. Bu fonksiyona çalışma zamanı meta verileri olarak adlandırdığım şeyleri ekliyorum.
Buradaki fikir şu; eğer birisi komutu çalıştırırken sorun yaşarsa, onun bir transkript başlatmasını, komutu -Verbose ile çalıştırmasını, transkripti durdurup bana göndermesini sağlayabilirim. Umarım ayrıntılı çıktı sorunu çözmeme yardımcı olabilir.
Kodu Alın
Şu ana kadar bazılarınız kodun geri kalanını arıyorsunuz. Bu üzerinde durmaya devam edebileceğim bir şey olduğundan Get-ADChange işlevini ve format dosyasını Github'da yayınladım. https://Gist.github.com/jdhitsolutions/3bce157bd64717dd616b949f6e280433 adresine gidin ve her iki dosyayı da alın. Dosyalar aynı klasöre gitmeli ve format dosyasının adchange.format.ps1xml olarak kaydedildiğinden emin olunmalıdır. Daha sonra komut dosyasını nokta kaynak olarak kullanabilirsiniz:
. c:\scripts\get-adchange.ps1Açıkçası uygun yolu kullanın. Betik aynı zamanda format dosyasını PowerShell oturumunuza da yükleyecektir. Get-ADChange komutunu ActiveDirectory modülünün kurulu olduğu bir Windows 10 masaüstünden çalıştırabilmeniz gerekir.
Bununla birlikte, bu kod hiçbir garanti veya destek olmaksızın olduğu gibi sunulmaktadır. Üretim dışı bir ortamda kapsamlı test yapmanızı şiddetle tavsiye ederim.
Özet
HTML raporlama betiğime geri dönebilir ve onu bu yeni işlevi kullanacak şekilde değiştirebilirim. Veya bunun etrafında başka denetleyici komut dosyaları oluşturabilirim. Tekrar belirtmek isterim ki, eğer daha büyük bir Active Directory altyapınız varsa, gerçek yönetim ve raporlama çözümlerine yatırım yaparak daha iyi hizmet alacaksınız. Bazı okuyucular kimin değişiklik yapmış olabileceğini keşfetmek istedi. Bu bilgiler Active Directory nesnesinde saklanmaz. Denetim ve günlük kaydının devreye girdiği ve "gerçek" bir yönetim ürününün yatırıma değer olduğu yer burasıdır.
Yine de umarım bundan bir PowerShell aracı oluşturma süreci hakkında bir şeyler öğrenirsiniz. Her zaman olduğu gibi soru ve yorumlarınızı bekliyoruz.




