Иногда бывает очень полезным найти какой-нибудь запрос в БД CA. Можно, конечно же, сделать это через certutil, но это не всегда удобно, потому что если под конкретный запрос подпадает несколько строк из БД, нужно уже вручную как-то парсить вывод, чтобы найти то, что нужно. Поэтому я решил рассказать, как наваять подобный костыль (только религиозно-православный) родными средствами PowerShell и необходимыми COM интерфейсами. Для работы с БД сервера CA нам понадобится лишь один интерфейс: ICertView2.
Каждая БД состоит из столбцов и рядов. То же самое относится и к БД CA (которая, кстати говоря, является стандартной встроенной Jet БД, что позволяет с ней работать стандартными тулзами типа eseutil). Ряды представляют собой набор свойств каждого запроса и для каждого запроса выделяется ровно один ряд. Столбцы представляют собой сами свойства. Каждому столбцу соответствует одно свойство. CA использует БД с заранее созданной (и неизменяемой) схемой, т.е. набором поддерживаемых столбцов. Давайте попробуем вывести схему БД. Для начала создадим объект ICertView2:
$CaView = New-Object -ComObject CertificateAuthority.View
Далее нужно подключиться к какому-то CA серверу при помощи метода OpenConnection. В качестве аргумента следует указать конфигурационную строку CA сервера вида CAComputerName\CAName.
$CaView.OpenConnection("dc1\Contoso CA")
Если ошибок не высыпало, значит, подключение произошло удачно. Теперь мы хотим посмотреть схему и это можно сделать при помощи метода EnumCertViewColumn. В качестве аргумента указываем CVRC_COLUMN_SCHEMA (которое имеет значение 0).
$CaView.EnumCertViewColumn(0)
В результате мы молучим другой объект интерфейса IEnumCERTVIEWCOLUMN. А теперь методом Next будем шагать по каждому столбцу и собирать сведения о нём, как: имя столбца, локализованное имя, тип данных и максимальный размер данных для этого столбца при помощи набора методов, описанных на страничке ICertView2. Вот как это выглядит:
PS C:\> $CaView = New-Object -ComObject CertificateAuthority.View PS C:\> $CA = "dc1\Contoso CA" PS C:\> $CaView.OpenConnection($CA) PS C:\> $Columns = $CaView.EnumCertViewColumn(0) PS C:\> $Columns.Next() 0 PS C:\> $Columns.GetName() Request.RequestID PS C:\> $Columns.GetDisplayName() Request ID PS C:\> $Columns.GetType() 1 PS C:\> $Columns.GetMaxLength() 4 PS C:\> $Columns.Next() 1 PS C:\> $Columns.GetName() Request.RawRequest PS C:\> $Columns.GetDisplayName() Binary Request PS C:\> $Columns.GetType() 3 PS C:\> $Columns.GetMaxLength() 65536 PS C:\>
После метода Next мы видим текущий индекс столбца. Что касается вывода метода GetType(), то вместо типа данных мы видим только циферки. Это нормальное поведение для CryptoAPI интерфейсов. Каждому числу соответствует свой тип данных (их поддерживается всего 4) и вот как они расшифровываются:
Если всё это затолкать в цикл DO…UNTIL, можно всё это дело автоматизировать. По правде говоря некоторые столбцы могут содержать массив данных и это можно проверить при помощи метода IsIndexed. Давайте теперь напишем окончательный скрипт, который нам по одному клику выдаст всю схему БД:
function Get-CADataBaseSchema { [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string]$CAConfig ) # создаём объект ICertView try {$CaView = New-Object -ComObject CertificateAuthority.View} catch {Write-Error "Unable to instantiate ICertView object"; return} # открываем подключение к CA $CaView.OpenConnection($CAConfig) # говорим, что мы хотим посмотреть схему $Columns = $CaView.EnumCertViewColumn(0) # начинаем итерацию по столбцам БД [void]$Columns.Next() do { # создаём временный объект, чтобы получить красивый вывод и наполняем его данными $Column = "" | Select Name, DisplayName, Type, MaxLength $Column.Name = $Columns.GetName() $Column.DisplayName = $Columns.GetDisplayName() $Column.Type = switch ($Columns.GetType()) { 1 {"Long"} 2 {"DateTime"} 3 {"Binary"} 4 {"String"} } [string]$Column.MaxLength = $Columns.GetMaxLength() if ($Columns.IsIndexed() -eq 1) {$Column.MaxLength += ", Indexed"} $Column } until ($Columns.Next() -eq -1) # закрываем подключение к БД $Columns.Reset() }
А вывод весьма простенький:
PS C:\> Get-CADataBaseSchema "dc1\Contoso CA" Name DisplayName Type MaxLength ---- ----------- ---- --------- Request.RequestID Request ID Long 4, Indexed Request.RawRequest Binary Request Binary 65536 Request.RawArchivedKey Archived Key Binary 65536 Request.KeyRecoveryHashes Key Recovery Agent Hashes String 8192 Request.RawOldCertificate Old Certificate Binary 16384 Request.RequestAttributes Request Attributes String 32768 Request.RequestType Request Type Long 4 Request.RequestFlags Request Flags Long 4 Request.StatusCode Request Status Code Long 4 Request.Disposition Request Disposition Long 4, Indexed Request.DispositionMessage Request Disposition Message String 8192 Request.SubmittedWhen Request Submission Date DateTime 8, Indexed Request.ResolvedWhen Request Resolution Date DateTime 8, Indexed Request.RevokedWhen Revocation Date DateTime 8 Request.RevokedEffectiveWhen Effective Revocation Date DateTime 8, Indexed Request.RevokedReason Revocation Reason Long 4 Request.RequesterName Requester Name String 2048, Indexed Request.CallerName Caller Name String 2048, Indexed Request.SignerPolicies Signer Policies String 8192 Request.SignerApplicationP... Signer Application Policies String 8192 Request.Officer Officer Long 4 <...>
В следующей части (или частях, пока ещё не придумал) поговорим о том, как блуждать по самой БД.
Comments: