Contents of this directory is archived and no longer updated.

В предыдущей части мы рассмотрели возможность извлечения схемы БД центров сертификации. По схожему принципу можно и делать выборку из неё посредством тех же COM интерейсов. Как я уже говорил, основным интерфейсом для доступа к БД будет ICertView2:

$CaView = New-Object -ComObject CertificateAuthority.View

Подключаемся к конкретному серверу CA при помощи метода OpenConnection:

$CaView.OpenConnection("dc1\contoso ca")

Для начала мы рассмотрим простой пример, выберем все строки из БД, но с заранее определёнными столбцами. Это нужно затем, чтобы не отображать ненужную информацию, которая будет мешать и поедать память. Каждая строка в БД максимально может занимать до полумегабайта места в памяти. Выглядит нестрашно, но когда у вас тысяча запросов в БД это уже будет примерно 500 мегабайт. Но тысяча запросов — это очень даже немного. Поэтому давайте для начала посмотрим все запросы вот в каком виде: номер запроса, имя реквестора (пользователя, от лица которого был подан запрос в CA), имя, на которое выдан сертификат, серийный номер сертификата и срок действия сертификата. Схемы БД для всех существующих Windows CA можно получить при помощи скрипта в предыдущей части или найти и в оффлайне: [MS-CSRA] Product Behavior, note 5.

Необходимые столбцы добавляются при помощи методов SetResultColumnCount, GetColumnIndex и SetResultColumn:

$CaView.SetResultColumnCount(6)
$Column0 = $CaView.GetColumnIndex($false,"RequestID")
$CaView.SetResultColumn($Column0)
$Column1 = $CaView.GetColumnIndex($false,"RequesterName")
$CaView.SetResultColumn($Column1)
<...>

Здесь я показал последовательность действий. Сначала задаём количество столбцов, которые будут возвращены. Далее извлекаем номер каждого столбца и добавляем его в результирующую таблицу. Но эту процедуру можно упростить до трёх строчек, вне зависимости от количества требуемых столбцов:

$properties = "RequestID","RequesterName","CommonName","NotBefore","NotAfter","SerialNumber"
$CaView.SetResultColumnCount($properties.Count)
$properties | %{$CAView.SetResultColumn($CAView.GetColumnIndex($False, $_))}

Если попытаетесь добавить столбцов больше, чем указано в методе SetResultColumnCount, получите ошибку. Поэтому сначала подсчитывайте количество требуемых столбцов и только после этого их добавлять. В принципе, теперь всё, можно начинать опрашивать БД. Для этого открываем её методом OpenView:

$Row = $CaView.OpenView()

Этот метод вернёт указатель на объект интерфейса IEnumCERTVIEWROW и начинаются шахматы (перевод шагового искателя в исходную позицию). Дальше уже нужно запускать цикл Do…Until или While…Do. Я предпочитаю второй вариант по той простой причине, что если если БД пустая (при указании дополнительных фильтров и ничего под него не подпало) первый же вызов метода Next вернёт –1. Поэтому нужно либо сразу отслеживать значение индекса или использовать такой тип цикла, где значение индекса проверяется перед запуском первой итерации цикла, как While…Do. И вот как это выглядит:

Внимание: если в БД CA находится большое количество запросов, вы получите огромную кучу объектов на выходе, потому что будут возвращены все запросы из секций Issued Certificates, Revoked Certificates и Failed Requests.

# начинаем шахматы и шагать шаговым искателем по строчкам
while ($Row.Next() -ne -1) {
    # создаём пустой объект, который будет являться нашим выходным объектом
    $cert = New-Object psobject
    # переставляем шаговый искатель с вертикального в горизонтальное направление
    $Column = $Row.EnumCertViewColumn()
    # шагаем последовательно по столбцам, которые мы определили вначале скрипта
    while ($Column.Next() -ne -1) {
        # извлекаем название текущего столбца
        $current = $Column.GetName()
        # добавляем свойство к нашему выходному объекту с именем равным имени столбца
        # и добавляем соответствующее значение столбца текущей строчки
        $Cert | Add-Member -MemberType NoteProperty $($Column.GetDisplayName()) -Value $($Column.GetValue(1)) -Force
    }
    # выкидываем объект на выход
    $Cert
    # сбрасываем положение горизонтального шагового искателя
    $Column.Reset()
}
# сбрасываем положение вертикального шагового искателя
$Row.Reset()

И вот как выглядит примерный вывод:

Issued Request ID           : 1
Requester Name              : CONTOSO\DC1$
Issued Common Name          : Contoso CA
Certificate Effective Date  : 2009.02.15. 14:31:15
Certificate Expiration Date : 2014.02.15. 14:40:11
Serial Number               : 5dd87e4cffe3b3bc43f608eb57c767f7

Issued Request ID           : 2
Requester Name              : CONTOSO\DC1$
Issued Common Name          : DC1.contoso.com
Certificate Effective Date  : 2009.02.15. 14:51:45
Certificate Expiration Date : 2010.02.15. 14:51:45
Serial Number               : 15109536000000000002

Issued Request ID           : 3
Requester Name              : CONTOSO\administrator
Issued Common Name          : Users
                              Administrator
Certificate Effective Date  : 2009.02.15. 15:04:02
Certificate Expiration Date : 2011.02.15. 15:04:02
Serial Number               : 151bd2c9000000000003

<...>

круто, да? Но здесь мы получили сведения о каждом запросе, а мы хотим получать что-то более конкретное, как быть? В следующий раз я как раз и покажу, как можно создавать более конкретные запросы, чтобы получать только результаты, подпадающие под определённый критерий.


Share this article:

Comments:

Comments are closed.