2016-02-10 2 views
0

В настоящее время у меня есть 8 доменов. Используя следующий код ...DirectorySearcher получить все контроллеры домена для списка доменов

$listOfDCs = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().DomainControllers 

ForEach ($DC in $listOfDCs) 
{ 
    Write-Host $DC 
} 

Я получаю 32 контроллера для одного домена. Любая идея, как я могу извлечь контроллеры для других доменов?

Примечание: Я хочу избежать использования командлетов квеста как можно больше.

Причиной этого является значение свойства lastlogon для каждого постоянного тока в домене. Я просто пытаюсь схватить последнюю. Вот рабочий код у меня есть для этого, но это не тянет последний один ...

$SamAccountName = "JohnDoe" 
$domainSearchProperties = @('SamAccountName','LastLogon', 'DistinguishedName') 
$domainDisplayOutputProperties = @('SamAccountName','LastLogon') 
$domainConnector = 'www.myplayground.com' 
$domainName = 'MyPlayground' 
$outputFile = 'C:\Scripts\Tests\testresults.csv' 

Function SearchSingleDomainAndExportContents 
{ 
    Param ([String]$SamAccountName, [String]$LocalOutputFileWithPath, [String[]]$domainSearchProperties, [String[]]$domainDisplayOutputProperties, [String]$domainConnector, [String]$domainName) 
    Write-Host "Starting sub-process to search with SamAccountName $SamAccountName in $domainName" 
    $searchDomainResultsTable = powershell -command { 
     Param ([String]$SamAccountName, [String]$LocalOutputFileWithPath, [String[]]$domainSearchProperties, [String[]]$domainDisplayOutputProperties, [String]$domainConnector, [String]$domainName) 
     $domain = "LDAP://$domainConnector" 
     $adDomain = New-Object System.DirectoryServices.DirectoryEntry($domain) 
     $adSearcher = New-Object System.DirectoryServices.DirectorySearcher($adDomain) 
     $adSearcher.Filter = "(&(objectCategory=User)(samAccountType:1.2.840.113556.1.4.803:=805306368)(sAMAccountName=$SamAccountName))" 
     $adSearcher.PageSize=1000 
     $adSearcher.PropertiesToLoad.AddRange($domainSearchProperties) | out-Null 
     $userRecords = $adSearcher.FindAll() | Where-Object {($_.DistinguishedName -notlike "*Retired*")} 
     $adSearcher.Dispose() | Out-Null 
     [System.GC]::Collect() | Out-Null 

     # The AD results are converted to an array of hashtables. 
     $userPropertiesTable = @() 
     foreach($record in $userRecords) { 
      $hashUserProperty = @{} 
      foreach($userProperty in $domainSearchProperties){ 
       if (($userProperty -eq 'objectGUID') -or ($userProperty -eq 'objectSid') -or ($userProperty -eq 'msExchMasterAccountSid')) { 
        if ($record.Properties[$userProperty]) { 
         $hashUserProperty.$userProperty = $record.Properties[$userProperty][0] 
        } else { 
         $hashUserProperty.$userProperty = $null 
        } 
       } Else { 
        if ($record.Properties[$userProperty]) { 
         $hashUserProperty.$userProperty = ($record.Properties[$userProperty] -join '; ').trim('; ') 
        } else { 
         $hashUserProperty.$userProperty = $null 
        } 
       } #end Else 
      } #end ForEach 
      $userPropertiesTable += New-Object PSObject -Property $hashUserProperty 
     } #end ForEach 
     [System.GC]::Collect() | Out-Null 

     # Fixes the property values to be a readable format before exporting to csv file 
     $listOfBadDateValues = '9223372036854775807', '9223372036854770000', '0' 
     $maxDateValue = '12/31/1600 5:00 PM' 
     $valuesToFix = @('lastLogonTimestamp', 'AccountExpires', 'LastLogon', 'pwdLastSet', 'objectGUID', 'objectSid', 'msExchMasterAccountSid') 
     $valuesToFixCounter = 0 
     $valuesToFixFound = @($false, $false, $false, $false, $false, $false, $false) 

     ForEach ($valueToFix in $valuesToFix) 
     { 
      if ($domainDisplayOutputProperties -contains $valueToFix) 
      { 
       $valuesToFixFound[$valuesToFixCounter] = $true 
      } 
      $valuesToFixCounter++ 
     } 

     $tableFixedValues = $userPropertiesTable | % { 
      if ($valuesToFixFound[0]) { 
       if ($_.lastLogonTimestamp) { 
        $_.lastLogonTimestamp = ([datetime]::FromFileTime($_.lastLogonTimestamp)).ToString('g') 
       } 
      }; if ($valuesToFixFound[1]) { 
       if (($_.AccountExpires) -and ($listOfBadDateValues -contains $_.AccountExpires)) { 
        $_.AccountExpires = "" 
       } else { 
        if (([datetime]::FromFileTime($_.AccountExpires)).ToString('g') -eq $maxDateValue) { 
         $_.AccountExpires = "" 
        } Else { 
         $_.AccountExpires = ([datetime]::FromFileTime($_.AccountExpires)).ToString('g') 
        } 
       } 
      }; if ($valuesToFixFound[2]) { 
       if (($_.LastLogon) -and ($listOfBadDateValues -contains $_.LastLogon)) { 
        $_.LastLogon = "" 
       } else { 
        if (([datetime]::FromFileTime($_.LastLogon)).ToString('g') -eq $maxDateValue) { 
         $_.LastLogon = "" 
        } Else { 
         $_.LastLogon = ([datetime]::FromFileTime($_.LastLogon)).ToString('g') 
        } 
       } 
      }; if ($valuesToFixFound[3]) { 
       if (($_.pwdLastSet) -and ($listOfBadDateValues -contains $_.pwdLastSet)) { 
        $_.pwdLastSet = "" 
       } else { 
        if (([datetime]::FromFileTime($_.pwdLastSet)).ToString('g') -eq $maxDateValue) { 
         $_.pwdLastSet = "" 
        } Else { 
         $_.pwdLastSet = ([datetime]::FromFileTime($_.pwdLastSet)).ToString('g') 
        } 
       } 
      }; if ($valuesToFixFound[4]) { 
       if ($_.objectGUID) { 
        $_.objectGUID = ([guid]$_.objectGUID).Guid 
       } Else { 
        $_.objectGUID = "" 
       } 
      }; if ($valuesToFixFound[5]) { 
       if ($_.objectSid) { 
        $_.objectSid = (New-Object Security.Principal.SecurityIdentifier($_.objectSid, 0)).Value 
       } Else { 
        $_.objectSid = "" 
       } 
      }; if ($valuesToFixFound[6]) { 
       if ($_.msExchMasterAccountSid) { 
        $_.msExchMasterAccountSid = (New-Object Security.Principal.SecurityIdentifier($_.msExchMasterAccountSid, 0)).Value 
       } Else { 
        $_.msExchMasterAccountSid = "" 
       } 
      };$_} 
      [System.GC]::Collect() | Out-Null 

      $sortedUserPropertiesTable = $tableFixedValues | Select-Object $domainDisplayOutputProperties 
      $finalDomainUserPropertiesTable = $sortedUserPropertiesTable | Select-Object -Property @{Name="Domain Name";Expression={$domainName}}, * 
      [System.GC]::Collect() | Out-Null 

      return $finalDomainUserPropertiesTable 
    } -args $SamAccountName, $LocalOutputFileWithPath, $domainSearchProperties, $domainDisplayOutputProperties, $domainConnector, $domainName 
    [System.GC]::Collect() | Out-Null 
    Write-Host "Search Complete." 
    Write-Host "" 

    $searchDomainResultsTable | Export-Csv $outputFile -NoTypeInformation -Force 
} 

Это будет извлекать данные только из 1 постоянного тока. Проблема с этим заключается в том, что существуют другие dc, где lastlogon содержит более позднюю дату, и это тот, который я за ним. Поэтому мне нужно запросить все dc, а затем просто экспортировать последнюю дату lastlogon для этого SamAccountName.

+0

Почему бы не просто используйте атрибут lastLogonTimestamp? –

+0

у него на самом деле гораздо более ранняя дата, чем LastLogon. Например ... 'LastLogon для этого dc в этом домене = 2/8/2016 10:00 am',' последний LastLogon для всех dc в этом домене = 2/10/2016 11:00 am', 'lastLogonTimestamp для этого dc в этом домене = 2/1/2016 9:00 am', –

+0

См. [«Атрибут LastLogonTimeStamp» - «Что он предназначен и как он работает»] (https://blogs.technet.microsoft.com/askds/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works /) для получения дополнительной информации об атрибуте lastLogonTimestamp. С этим пониманием, почему вы не можете его использовать? –

ответ

0

Вы можете получить другие домены, используя класс .Net Domain, например, для своего текущего домена. Сначала вам нужно создать контекст для домена, на который настроен таргетинг, а затем вы можете получить информацию о домене, включая DC.

$DomainList = 'Domain1.com','Domain2.com','Domain3.com','Domain4.com','Domain5.com','Domain6.com','Domain7.com','Domain8.com' 
$AllDCs = $DomainList | ForEach{ 
    $DomContxt = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList ('Domain',$_) 
    $Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomContxt) 
    $Domain.DomainControlers 
} 
+0

Я думаю, что OP пытается «автообнаружить» другие домены в лесу –

+0

интересно, я не знал, что DomainControlers существует как возвращаемое значение для сборки DirectoryServices ... После того, как я закончу свою логику, я могу попробовать это. Теперь они хотели, чтобы это было сделано 2 дня назад, и до сих пор у меня нет ничего для них ... Вопрос - это «Именитель» в домене «For Domain» для массива доменов или это значение по умолчанию для этого 'DirectoryContext -ArgumentList'? –

+0

Термин «Домен» представляет собой значение из списка «DirectoryContextType», найденного здесь [https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.directorycontexttype (v = vs. 110) .aspx). – TheMadTechnician

0

Если ваш компьютер уже является членом домена, поиск всех других доменов в лесу проще, чем вы думаете.

Просто поиск crossRef объектов (эти ссылки между разделами базы данных на контроллере домена и логические контексты именования в лесу - такие, как домены), которые их значение systemFlag атрибута установлены в 0x3. Они все хранятся в одном контейнере в контексте именования конфигурации:

# connect to the RootDSE - the yellow pages of Active Directory 
$RootDSE = [adsi]"LDAP://RootDSE" 
# grab the distinguished name of the forest-wide configuration naming context 
$ConfigDN = $RootDSE.configurationNamingContext.ToString() 

# Create a new directory search 
$ConfigSearcher = [adsisearcher]"" 

# Configure the searcher to look for domain cross-ref's 
$ConfigSearcher.SearchRoot = "LDAP://$ConfigDN" 
$ConfigSearcher.Filter = "(&(objectClass=crossRef)(systemFlags=3))" 
[void]$ConfigSearcher.PropertiesToLoad.AddRange(@('dnsRoot','nCName','nETBIOSName')) 
$Domains = $ConfigSearcher.FindAll() 

# Grab only the three most interesting pieces of info 
# The fully qualified DNS name, e.g. domain.forest.tld 
# The NetBIOS shortname, e.g. DOMAIN 
# The distinguished name to the domain root, e.g DC=domain,DC=forest,DC=tld 
$Domains = $Domains |Select @{Name="DomainFQDN";Expression={$_.Properties['dnsRoot']}},@{Name='NetBIOSName';Expression={$_.Properties['nETBIOSName']}},@{Name='DN';Expression={$_.Properties['nCName']}} 
+0

Спасибо за ответ, но у меня уже есть модуль, в котором домены жестко закодированы. Для этого мне нужен автоматический поиск контроллеров домена. Например ... domain1.com = 32 контроллера домена, domain2.com = 28 контроллеров домена, domain3.com = 2 контроллеров домена и т. Д. Затем мне придется переделать код, чтобы пользователь указал домен , и запустите цикл поиска через каждый dc для этого домена, вычислите, какой 'LastLogon' является последним, и экспортируйте только это значение для этого' SamAccountName' в файл csv. –

-1

Кроме того, из командной строки можно задать DNS-сервера для IP-адреса всех контроллеров домена

NSlookup.exe domain1

Смежные вопросы