Contents of this directory is archived and no longer updated.

А знаете ли вы как можно легко получить список всех Enterprise CA в текущем домене? А в текущем лесу? Оказывается это очень легко! ADSI — самый лучший способ, если вы хотите пошариться в своей базе AD. Список таких CA находится по пути:

CN=Enrollment Services, CN=Public Key Services, CN=Services, CN=Configuration, DC=Domain, DC=COM

Последние 2 значения уже будут отличаться в зависимости от имени домена. Чтобы получить список объектов по этому пути нужно просто создать соответствующий LDAP объект. Объект делается просто, сначала указывается тип объекта [ADSI], следом идёт префикс ссылки LDAP:// (почти как HTTP://) и после префикса уже этот путь (который называется Distinguished Name или просто DN):

[Administrator] $CA = [ADSI]"LDAP://CN=Enrollment Services, CN=Public Key Services, CN=Services, CN=Configuration, DC=co
ntoso,DC=COM"
[Administrator] $CA


distinguishedName : {CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=com}
Path              : LDAP://CN=Enrollment Services, CN=Public Key Services, CN=Services, CN=Configuration, DC=contoso,DC
                    =COM
[Administrator] $CA.distinguishedName
CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=com

Если посмотреть этот путь в ADSIEdit.msc, то мы увидим, что это контейнер. А раз это контейнер, то нам нужно в него заглянуть. Здесь, к сожалению, нельзя сделать dir $CA.distinguishedName, а так хочется. Чтобы посмотреть содержимое нужно использовать свойство Children (ворненк, дети отаке!):

[Administrator] $ca.Children


distinguishedName : {CN=contoso-DC2-CA,CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=co
                    ntoso,DC=com}
Path              : LDAP://CN=contoso-DC2-CA,CN=Enrollment Services,CN=Public Key Services, CN=Services, CN=Configurati
                    on, DC=contoso,DC=COM

distinguishedName : {CN=Contoso CA,CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=contos
                    o,DC=com}
Path              : LDAP://CN=Contoso CA,CN=Enrollment Services,CN=Public Key Services, CN=Services, CN=Configuration,
                    DC=contoso,DC=COM



[Administrator]

Уже отсюда невооружённым глазом видны имена CA. Собственно, можно показать только имя самого CA и компьютера, на котором работает этот CA:

[Administrator] $ca.Children | ft Name, DNSHostName

Name                                                        DNSHostName
----                                                        -----------
{contoso-DC2-CA}                                            {dc2.contoso.com}
{Contoso CA}                                                {DC1.contoso.com}


[Administrator]

Здесь есть один важный нюанс. Если получить этот LDAP объект в PowerShell 1.0, то он будет содержать только Distinguished Name, а свойство Children будет отсутствовать в нём. Для этого нужно воспользоваться свойством PSBase, в котором уже будет Children. Командой Select можете выводить на экран и другие свойства, какие вы захотите:

PS C:\> $ca.children


MemberType          : Method
OverloadDefinitions :
TypeNameOfValue     : System.Management.Automation.PSMethod
Value               :
Name                : children
IsInstance          : True



PS C:\> $ca.psbase.children

distinguishedName
-----------------
{CN=contoso-DC2-CA,CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=com}
{CN=Contoso CA,CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=com}


PS C:\> $ca.psbase.children | select Name, DNSHostname

Name                                                        DNSHostname
----                                                        -----------
{contoso-DC2-CA}                                            {dc2.contoso.com}
{Contoso CA}                                                {DC1.contoso.com}


PS C:\>

Поэтому для обратной совместимости между версиями лучше использовать PSBase. В этом объекте будут содержаться не только CA вашего домена, а во всех доменах вашего леса, поскольку эта часть AD реплицируется как Forest naming context, т.е. между всеми контроллерами в лесу. Жизнь была бы неинтересной, если в каждом новом домене приходилось бы переписывать хвост (которая определяет домен, в котором следует искать) каждый раз. Для универсальности можно пойти на военную хитрость — раздобыть FQDN текущего домена, разобрать его и воткнуть в LDAP запрос. Получить имя текущего домена можно очень просто, с использованием статического метода GetCurrentDomain() класса System.DirectoryServices.ActiveDirectory.Domain. На самом деле у этого класса есть ещё куча других полезных методов, поэтому не лишним будет заглянуть по ссылке.

PS C:\> [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()


Forest                  : contoso.com
DomainControllers       : {DC1.contoso.com}
Children                : {}
DomainMode              : Windows2003Domain
Parent                  :
PdcRoleOwner            : DC1.contoso.com
RidRoleOwner            : DC1.contoso.com
InfrastructureRoleOwner : DC1.contoso.com
Name                    : contoso.com



PS C:\>

И свойство Name будет содержать имя нашего домена. Что дальше? А дальше, вполне очевидно, что нам надо заменить все точки на строку вида ", DC=". Вот так:

PS C:\> "contoso.com" -replace "\.", ", DC="
contoso, DC=com

А перед первым именем эту часть можно написать ручками. В итоге универсальная часть кода получится вот такая:

$domain = ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).Name
$domain = "DC=" + $domain -replace '\.', ", DC="
$CA = [ADSI]"LDAP://CN=Enrollment Services, CN=Public Key Services, CN=Services, CN=Configuration, $domain"

Вот теперь у нас есть всё необходимое, чтобы написать простеньку функцию:

function Get-CertificationAuthority ([string]$CAName) {
    $domain = ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).Name
    $domain = "DC=" + $domain -replace '\.', ", DC="
    $CA = [ADSI]"LDAP://CN=Enrollment Services, CN=Public Key Services, CN=Services, CN=Configuration, $domain"
    $CAs = $CA.psBase.Children | %{
        $current = "" | Select CAName, Computer
        $current.CAName = $_ | %{$_.Name}
        $current.Computer = $_ | %{$_.DNSHostName}
        $current
    }
    if ($CAName) {$CAs = @($CAs | ?{$_.CAName -eq $CAName})}
    if ($CAs.Count -eq 0) {throw "Sorry, here is no CA that match your search"}
    $CAs
}

Если выполнить эту функцию без аргументов, то она вернёт все CA в лесу. Но можно указать и какой-то один для каких-то других целей.


Share this article:

Comments:

Comments are closed.