Powershell - Выгрузка сайтов и подсетей Active Directory

Записка от 16.09.2013

Для одного моего веб-приложения, который определяет подсеть, из которой пришел запрос и на каком доменном контроллере нужно выполнить команду, потребовалось знать структуру сайтов в домене. Для того, чтобы дать приложенияю такую информацию, я задумал регулярно выгружать сайты и подсети из 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, который используется для идентификации подсетей пользователей в веб-приложении.

Вверх