Для одного моего веб-приложения, который определяет подсеть, из которой пришел запрос и на каком доменном контроллере нужно выполнить команду, потребовалось знать структуру сайтов в домене. Для того, чтобы дать приложенияю такую информацию, я задумал регулярно выгружать сайты и подсети из Active Directory в XML-файл. Выполнить эту задачу мне помог PowerShell, а именно скрипт, который представлен ниже.
# Получение папки скрипта $ScriptPath = $MyInvocation.MyCommand.Path $ScriptFolder = Split-Path $scriptpath # Получение сайтов из Active Directory $Sites = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Sites $SitesX = @() ForEach ($Site in $Sites) { $SitesX += New-Object -Type PSObject -Property ( @ "SiteName" = $site.Name "DomainController" = $Site.Servers[0].Name } ) } # Получение подсетей из Active Directory и сопоставление их с доменными контроллерами из таблицы сайтов $SitesAndSubnets = @() $Subnets = [ADSI]"LDAP://CN=Subnets,CN=Sites,CN=Configuration,DC=domain,DC=com" ForEach ($CurrentSubnet in $Subnets.children) { $Network = [ADSI]"$($CurrentSubnet.Path)" $st = $($Network.siteobject).split(",") $SiteName = $st[0].Replace("CN=","") ForEach ($CurrentSite in $SitesX) { If ($CurrentSite.SiteName -eq $SiteName) { $DomainController = $CurrentSite.DomainController } } $SitesAndSubnets += New-Object -Type PSObject -Property ( @ "IPAddress" = $($Network.cn) "Site" = $SiteName "DomainController" = $DomainController "Description" = $($Network.description) } ) } # Удаление из таблицы строк без описаний и без доменных контроллеров $SitesAndSubnetsFinal = @() ForEach ($CurrentSitesAndSubnet in $SitesAndSubnets) { If (($CurrentSitesAndSubnet.DomainController -ne $Nothing) -and ` ($CurrentSitesAndSubnet.Description -ne $Nothing)) { $SitesAndSubnetsFinal += $CurrentSitesAndSubnet } } # Сортировка таблицы по описаниям $SitesAndSubnetsFinal = $SitesAndSubnetsFinal | Sort-Object -Property "Description" # Сохранение таблицы в XML-файл $OutpupFilePath = $ScriptFolder + "\NetworkStructure.xml" $XmlWriter = New-Object System.XMl.XmlTextWriter($OutpupFilePath,$Null) # Установка типа форматирования $xmlWriter.Formatting = "Indented" $xmlWriter.Indentation = "4" # Начало XML-документа $xmlWriter.WriteStartDocument() # Установка XSL-стилей, если есть # $XSLPropText = "type='text/xsl' href='style.xsl'" # $xmlWriter.WriteProcessingInstruction("xml-stylesheet", $XSLPropText) # Начало корневого элемента $xmlWriter.WriteStartElement("NetworkStructure") # Запись инфоррмационных узлов документа $xmlWriter.WriteStartElement("Subnet") $xmlWriter.WriteElementString("IPAddress", "0.0.0.0/0") $xmlWriter.WriteElementString("Site", "Unknown") $xmlWriter.WriteElementString("DomainController", "W8SRV701") $xmlWriter.WriteElementString("Description", "Unknown") $xmlWriter.WriteEndElement() # <-- Closing Subnets ForEach ($CurrentSitesAndSubnetsFinal in $SitesAndSubnetsFinal) { $xmlWriter.WriteStartElement("Subnet") $xmlWriter.WriteElementString("IPAddress", $CurrentSitesAndSubnetsFinal.IPAddress) $xmlWriter.WriteElementString("Site", $CurrentSitesAndSubnetsFinal.Site) $xmlWriter.WriteElementString("DomainController", $CurrentSitesAndSubnetsFinal.DomainController) $xmlWriter.WriteElementString("Description", $CurrentSitesAndSubnetsFinal.Description) $xmlWriter.WriteEndElement() # <-- Closing Subnets } # Конец корневого элемента $xmlWriter.WriteEndElement() # <-- Closing RootElement # Конец XML-документа $xmlWriter.WriteEndDocument() # Закрытие XML-файла $xmlWriter.Finalize $xmlWriter.Flush() $xmlWriter.Close()
Результатом работы скрипта является XML-файл, который появляется в той же папке, в которой лежит скрипт. Структура сайтов и подсетей в этом файле быглядит так:
<?xml version="1.0"?> <NetworkStructure> <Subnet> <IPAddress>0.0.0.0/0</IPAddress> <Site>Unknown</Site> <DomainController>W8SRV701</DomainController> <Description>Unknown</Description> </Subnet> <Subnet> <IPAddress>10.107.213.192/26</IPAddress> <Site>Site1</Site> <DomainController>W8SRV01.domain.com</DomainController> <Description>RU - Bataysk (Sovhoznaya str.)</Description> </Subnet> </NetworkStructure>
Чтобы поставить скрипт в расписание сервера, пришлось изменить политику выполнения криптов на сервере - разрешить выполнение локальных неподписанных скриптов командой
set-executionpolicy remotesigned
Далее потребовалось написать CMD-файл для вызова PowerShell и поставить этот файл в расписание сервера, чтобы обновлять XML-файл еженедельно:
powershell.exe "%~DP0NetworkStructure.ps1"
Результатом проделанной работы является еженедельно обновляемый XML-файл NetworkStructure.xml, который используется для идентификации подсетей пользователей в веб-приложении.