PowerShell ile Grup İlkesi Bağlantılarını Alın
Geçenlerde arkadaşım Gladys Kravitz ile Grup İlkesi raporlama işleri hakkında sohbet ediyordum. ve tartışma beni PowerShell kullanarak Grup İlkesi bağlantılarını almak için sahip olduğum bazı eski kodların tozunu almaya yöneltti. GroupPolicy modülünün bir Set-GPLink komutu vardır, ancak sitenize, etki alanınıza ve kuruluş birimlerinize hangi GPO'ların bağlı olduğunu size kolayca gösteren hiçbir şey yoktur. Böyle bir rapora ihtiyacınız olmasa da, senaryo yazma tekniklerimde size yardımcı olacak bir şeyler olduğunu umuyorum.
Temel Komutla Başlayın
Tüm PowerShell projelerinde olduğu gibi konsoldan başlamak istiyorsunuz. Hedefinizin özünü size verecek bir komutu etkileşimli olarak çalıştırabilir misiniz? Benim durumumda bu, GroupPolicy modülündeki Get-GPInheritance cmdlet'idir. Yardım ve örnekleri okuyacağınız konusunda size güveneceğim. Etki alanı düzeyinde neyin bağlantılı olduğunu bana şu şekilde gösteriyor.
Çıktıya baktığımda muhtemelen peşinde olduğum bilgiyi içeren bir özellik görüyorum.
Bu umut verici görünüyor. Kuruluş birimleriyle de çalıştığını doğrulayabiliyorum.
(Get-ADOrganizationalUnit -filter * | Get-GPInheritance).GpoLinks |
Select-Object -Property Target,DisplayName,Enabled,Enforced,Order |
Format-TableBu oldukça iyi görünüyor ve başarmayı umduğum şeye yakın.
Site Bağlantılarını Sorgulama
Peki ya siteler? Tüm sitelerimin ayırt edici adlarını bilmediğimi varsayarak programatik bir çözüm istiyorum. Siteleri keşfetmek için ActiveDirectory modülünü kullanabilirim.
$getADO = @{
LDAPFilter = "(Objectclass=site)"
properties = "Name"
SearchBase = (Get-ADRootDSE).ConfigurationNamingContext
}
$sites = Get-ADObject @getADOYalnızca tek bir sitem var ancak ne yazık ki Get-GPInheritance siteleri kullanamıyor. Active Directory'yi derinlemesine incelemenin ve site bağlantılarını ayrıştırmanın yolları var, ancak ben daha kolay bir yol seçmeye ve eski COM nesnesi olan GPMGMT.GPM'ye başvurmaya karar verdim. İşte nasıl yapılacağı.
Öncelikle bir nesne referansına ihtiyacım var. Ayrıca nesnenin ihtiyaç duyduğu tüm sabitleri de alacağım.
$gpm = New-Object -ComObject "GPMGMT.GPM"
$gpmConstants = $gpm.GetConstants()Etki alanı ve ormana ilişkin referanslara ihtiyacım olacak.
$gpmdomain = $gpm.GetDomain("company.pri", "", $gpmConstants.UseAnyDC)
$SiteContainer = $gpm.GetSitesContainer("company.pri", "company.pri", $null, $gpmConstants.UseAnyDC)Etki alanım ve ormanımın adı Company.pri.
$SiteContainer nesnesinin bir GetSite() yöntemi vardır, ancak bir sitenin adına ihtiyaç duyar. Ama bunu daha önce anladım.
Bu yeni nesnenin GetGPOLinks() adında bir yöntemi var.
Bu oldukça iyi. Eksik olan tek şey GPO adı.
$site.GetGPOLinks() | Select GPOId,@{Name="DisplayName";Expression = {$gpmdomain.GetGPO($_.gpoid).Displayname}},Enabled,Enforced,SOMLinkOrderGPOId'ye sahip olduğum için GPO'yu alabilirim. Bu kod COM nesnesini kullanıyor. Cmdlet'i kullanabilirdim ama {} karakterlerini ayrıştırmam gerekecekti.
$site.GetGPOLinks() | Select GPOId,@{Name="DisplayName";Expression = {(Get-GPO -id ($_.gpoid.replace("{|",""))).Displayname}},Enabled,Enforced,SOMLinkOrderBu parçalar yerinde olduğunda, bu kod parçacıkları etrafında bir PowerShell aracı oluşturabilirim.
GPLink'i edinin
Get-GPLink adında bir fonksiyon yazdım. GroupPolicy ve ActiveDirectory cmdlet'lerini kullandığım ve bunlar bir sunucu ve/veya etki alanı belirlemeyi desteklediği için bunu da desteklemek istedim. Başlangıçta sıçramayı kullanmaya ve parametre değerlerini dinamik olarak atamaya çalıştım. Ancak bu hızla hantallaştı. Bunun yerine, $PSDefaultParameter değerlerinin komut dosyası kapsamı sürümünü tanımlıyorum.
if ($Server) {
$script:PSDefaultParameterValues["Get-AD*:Server"] = $server
$script:PSDefaultParameterValues["Get-GP*:Server"] = $Server
}
if ($domain) {
$script:PSDefaultParameterValues["Get-AD*:Domain"] = $domain
$script:PSDefaultParameterValues["Get-ADDomain:Identity"] = $domain
$script:PSDefaultParameterValues["Get-GP*:Domain"] = $domain
}Artık endişelenmeme gerek yok Get-ADDomain'i çalıştırdığımda ve fonksiyonumdan Server parametresi kullanılıyorsa Get-ADDomain cmdlet'i otomatik olarak onu kullanacaktır.
İşlev, GroupPolicy modülünü kullanarak etki alanını ve kuruluş birimlerini inceler ve sorgular. Site düzeyindeki bağlantılar COM nesnesi kullanılarak alınır. Teknik olarak COM nesnesini her şey için kullanabilirdim.
İşlev, GPO adına göre filtreleme sunmama veya yalnızca etkin veya devre dışı bağlantıları göstermeme olanak tanıyan tüm bağlantıları toplar.
Bu çok kötü değil. Ama her zaman daha fazlasını istiyorum. Örneğin, fonksiyonumun çıktısını Get-GPO'ya aktaramıyorum. Gerçi küçük bir ayarlama yaparsam yapabilirim.
Ama bunu sürekli yapmak istemiyorum. Ayrıca bir tablonun varsayılan çıktısını da istiyorum. Bunu özel bir format.ps1xml dosyası ve güvenilir New-PSFormatXML komutumla yapabileceğimi biliyorum. Ancak bunu yapmak için benzersiz ve özel bir tür adına ihtiyacım var.
Kodumda, genellikle yaptığım gibi sıfırdan özel bir nesne oluşturmadığım için yeni bir tür adı ekleyebiliyorum.
$results.GetEnumerator().ForEach( { $_.psobject.TypeNames.insert(0, "myGPOLink") })Yeni bir tür adıma sahip olduktan sonra tür uzantılarını tanımlayabilirim.
Update-TypeData -MemberType AliasProperty -MemberName GUID -Value GPOId -TypeName myGPOLink -Force
Update-TypeData -MemberType AliasProperty -MemberName Name -Value DisplayName -TypeName myGPOLink -Force
Update-TypeData -MemberType AliasProperty -MemberName GPO -Value DisplayName -TypeName myGPOLink -Force
Update-TypeData -MemberType AliasProperty -MemberName Link -Value Target -TypeName myGPOLink -Force
Update-TypeData -MemberType AliasProperty -MemberName Domain -Value GpoDomainName -TypeName myGPOLink -Force
Update-TypeData -MemberType ScriptProperty -MemberName TargetType -Value {
switch -regex ($this.target) {
"^((ou)|(OU)=)" { "OU" }
"^((dc)|(DC)=)" { "Domain" }
"^((cn)|(CN)=)" { "Site" }
Default { "Unknown"}
}
} -TypeName myGPOLink -ForceBu, Grup İlkesi bağlantılarımla çalışmayı artık çok daha kolay hale getiriyor.
Özel Biçim
Elbette, özel bir türüm olduğu için format.ps1xml dosyası oluşturup gerçekten havalı olabiliyorum. Artık sonuçların varsayılan tablo görünümünü oluşturabilirim. Her zaman PowerShell'e renk eklemenin yollarını aradığım için, devre dışı bırakılan bağlantıları ve ANSI çıkış dizileri kullanılarak uygulanan bağlantıları vurgulamaya karar verdim.
<TableColumnItem>
<ScriptBlock>
<!-- use ANSI formatting if using the console host-->
if ($host.name -eq 'ConsoleHost') {
if ($_.Enabled) {
$_.Enabled
}
else {
"$([char]0x1b)[1;91m$($_.enabled)$([char]0x1b)[0m"
}
}
else {
$_.Enabled
}
</ScriptBlock>
</TableColumnItem>Komut dosyası bloğu yalnızca PowerShell bir konsol ana bilgisayarını algılarsa ANSI'yi kullanır. Hem Windows PowerShell hem de PowerShell 7.x'te çalışacak bir kaçış dizisi kullanıyorum
Format dosyası başka görünümleri de içerir.
Özet
Çalışmalarımın çoğunda az önce anlattığım iş akışını kullanıyorum. Temel komutlarla başlıyorum, komutların etrafında bir işlev biçiminde sağlam bir sarmalayıcı oluşturuyorum, boru hattına bir nesne yazıyorum ve gerekirse tür ve biçim uzantılarıyla özelleştiriyorum. Nihai sonuç, diğer PowerShell komutları gibi işlem hattında çalışan, kullanımı kolay ve yararlı bir PowerShell aracı olmalıdır.
Tüm bunların nasıl çalıştığını görmek istiyorsanız kodu GitHub özeti olarak yayınladım. Denemek istiyorsanız her iki dosyayı da aynı dizine kaydetmeniz gerekir. İşlev dosyasını nokta kaynakladığınızda yüklendiğinden, biçim dosyasının adına çok dikkat edin.
Ne yaptığım veya neden yaptığım hakkında sorularınız varsa, lütfen yorum bırakmaktan çekinmeyin.













