Contents of this directory is archived and no longer updated.

Posts on this page:

А знаете ли вы, что объекты типа PsObject можно создавать очень легко?

Очень часто в скриптах мы создаём свои кастомайзенные объекты, наделяем их необходимыми свойствами, в которые уже записываем данные, полученные в процессе работы скрипта. Как это делается в классическом случае:

$Object = New-Object System.Management.Automation.PSObject
$Object | Add-Member NoteProperty Computer  ([PSObject]$null)
$Object | Add-Member NoteProperty Name  ([PSObject]$null)
$Object | Add-Member NoteProperty Path  ([PSObject]$null)
$Object | Add-Member NoteProperty Description  ([PSObject]$null)
...

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

[vPodans] $Object = New-Object System.Management.Automation.PSObject [vPodans] $Object | Add-Member NoteProperty Computer ([PSObject]$null) [vPodans] $Object | Add-Member NoteProperty Name ([PSObject]$null) [vPodans] $Object | Add-Member NoteProperty Path ([PSObject]$null) [vPodans] $Object | Add-Member NoteProperty Description ([PSObject]$null) [vPodans] $object | gm TypeName: System.Management.Automation.PSCustomObject Name MemberType Definition ---- ---------- ---------- Equals Method System.Boolean Equals(Object obj) GetHashCode Method System.Int32 GetHashCode() GetType Method System.Type GetType() ToString Method System.String ToString() Computer NoteProperty Computer=null Description NoteProperty Description=null Name NoteProperty Name=null Path NoteProperty Path=null [vPodans]

Но этот процесс можно сделать ещё более простым и коротким:

$Object = "" | Select Computer, Name, Path, Description

Смотрим:

[vPodans] $Object = "" | Select Computer, Name, Path, Description [vPodans] $object | gm TypeName: Selected.System.String Name MemberType Definition ---- ---------- ---------- Equals Method System.Boolean Equals(Object obj) GetHashCode Method System.Int32 GetHashCode() GetType Method System.Type GetType() ToString Method System.String ToString() Computer NoteProperty Computer=null Description NoteProperty Description=null Name NoteProperty Name=null Path NoteProperty Path=null [vPodans]

Видите, в результате объект получился такой же, зато как эффективно! Но и это ещё не всё. Если с Add-Member мы могли сразу присваивать значения параметру через параметр –Value командлета Add-Member, то и здесь мы можем на стадии создания объекта ему что-то присвоить. Присвоение производится по схеме:

$var = ""  | Select @{n = "PropertyName";e={"PropertyValue"}}

Для примера сделаем простой объект с несколькими свойствами и сразу при создании запишем в них значения:

$Object = "" | Select @{n='Computer';e={"компик"}},`@
{n=Name;e={"имя"}},@{n="Path";e={"вот тут путь какой-то"}}

проверяем:

[vPodans] $Object = "" | Select @{n='Computer';e={"компик"}},` >> @{n='Name';e={"имя"}},@{n="Path";e={"вот тут путь какой-то"}} >> [vPodans] $Object | gm TypeName: Selected.System.String Name MemberType Definition ---- ---------- ---------- Equals Method System.Boolean Equals(Object obj) GetHashCode Method System.Int32 GetHashCode() GetType Method System.Type GetType() ToString Method System.String ToString() Computer NoteProperty System.String Computer=компик Name NoteProperty System.String Name=имя Path NoteProperty System.String Path=вот тут путь какой-то [vPodans] $Object | fl * Computer : компик Name : имя Path : вот тут путь какой-то [vPodans]

Вот такими небольшими трюками мы позволяем делать PowerShell очень удобным и простым инструментом.

Вобщем, как говорится - As always enjoy the automation of tools within powershell.exe! © Flowering Weeds :-)

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

Введение

Сегодня хочу поговорить про OCSPOnline Certificate Status Protocol, который служит для проверки статуса сертификата на предмет отозванности. Как известно, стандартным механизмом проверки статуса сертификата является публикация CRL (Certificate Revocation List). В жизни существует 2 вида CRL:

  • Base CRL – полный список CRL, в котором указываются серийные номера всех отозванных в CA сертификатов и причина отзыва. Поддерживается всеми современными системами Windows. Характеризуется большим объёмом и не очень частой публикацией для уменьшения трафика.
  • Delta CRL – инкрементальный (хотя по факту это скорее дифференциальный) список CRL, в который включаются только сертификаты, которые были отозваны с момента последней публикации полного Base CRL. Характеризуется небольшим объёмом и относительно частой публикацией. Нативно поддерживается только системами не ниже Windows XP. Windows 2000 нативно не умеет его читать, но это становится возможным после применения патча MS04-011.

Опыт использования технологии CRL в широкой массе показал её негативные стороны. Если говорить о Base CRL, то Windows Server 2003/2008 по умолчанию публикуют этот список раз в неделю и в него включаются все сертификаты, которые были выданы и отозваны с момента последнего обновления сертификата CA. Т.к. эти сертификаты как правило выдаются на долгий срок (от 5 до 20 лет), то эти списки со временем могут сильно распухнуть. Из-за этого клиенту для проверки сертификата нужно вытягивать весь Base CRL с CA и искать там требуемый сертификат. Кстати, почему HTTPS сайты частенько тормозят :-) Учитывая, что Base CRL публикуются не очень часто, то для обеспечение наиболее актуального списка CRL была внедрена система Delta CRL, которая включает в себя только сертификаты, которые были отозваны с момента последней публикации Base CRL. По умолчанию CA под управлением Windows Server 2003/2008 публикуют его раз в сутки.

Но это не отменяет необходимости клиенту как скачивать не только Base CRL, но и приходится дополнительно скачивать Delta CRL. Однако Certificate Services в Windows Server 2008 позволяют нам сделать жизнь чуточку лучше и облегчить процесс валидации сертификата за счёт использования OCSP.

Вкратце, OCSP работает очень просто: клиент для проверки статуса сертификата отправляет запрос на OCSP Responder с указанием серийного номера проверяемого сертификата. OCSP Responder на своей стороне проверяет статус сертификата и возвращает этот статус клиенту.

Примечание: использовать протокол OCSP нативно умеют только клиенты под управлением Windows Vista и выше. Предыдущие ОС могут его поддерживать только за счёт сторонних компонентов.

Настройка шаблона CA

Итак, для начала нам потребуется установленный в сети Certification Authority под управлением Windows Server 2008 (любой редакции, кроме Web). По умолчанию с добавлением роли  AD CS добавляется и служба Online Respnder. Для этого так же потребуется установить службы IIS, о чём мастер вам сообщит и предложит сделать. На сервере CA необходимо запустить оснастку Certificate Templates (Start –> Run... –> certtmpl.msc) и там найти шаблон OCSP Response Signing:

OCSP Template fig.1

Данный шаблон характеризуется следующими свойствами:

  • срок действия сертификата составляет 2 недели
  • на вкалдке Request Handlings добавлено право чтения приватного ключа для службы Network Service, поскольку служба OCSP работает от лица Network Service, а не LocalSystem (для LocalSystem отдельных разрешений не требуется)
  • шаблон не содержит CDP и AIA расширений
  • шаблон помечен как неподлежащий для проверки на отзыв (см. fig.1)

На вкладке Security необходимо для учётной записи компьютера, на котором размещён OCSP выдать право Allow Read и Allow Enroll. Это единственное изменение, которое необходимо выполнить для шаблона. Теперь нужно открыть оснастку Certificate Authority и добавить этот шаблон для выдачи:

правой кнопкой на Certificate Templates –> New –> Certificate Template to Issue –> OSCP Response Signing. Далее нужно создать оснастку Certificates для учётной записи компьютера и запросить сертификат на основе этого шаблона с компьютера, где установлен OCSP Responder.

После запроса сертификата не стоит закрывать оснастку Certificates, а выбрать новый сертификат и в All Tasks выбрать Manage Privete keys. В открывшемся окне Permissions выдайте право Read для учётной записи Network Service:

Permissions for OCSP Private Key fig.2

Настройка CA

Следующим этапом нужно подготовить сам CA для работы с OCSP. Для этого вызываем свойства самого CA и переходим на вкладку Extensions:

CA Extensionsfig.3

В списке Extensions выбираем Authority Information Access (AIA), нажимаем Add и в поле вписываем URL для OCSP. В моём случае это http://dc2.contoso.com/ocsp. А так же выставляем нижнюю галочку, чтобы этот путь добавлялся во все издаваемые этим CA сертификаты.

Примечание от 09.08.2009: здесь у меня опечатка на скриншоте - нужно поставить только одну галочку, а именно - только нижнюю. Адрес OCSP не нужно добавлять в AIA издаваемых сертификатов, иначе клиент будет с OCSP адреса пытаться скачать CRT файл.

Примечание: учитвая, что срок действия такого сертификата всего 2 недели, не следует этот шаблон добавлять в Autoenrollment (если используется) Policies, т.к. тут возможны трудности с валидацией сертификата на отрезке времени когда обновляется сертификат CA. Вот как это может выглядеть:

Renewal issuesfig.4

в промежутке t0 – t2 используется старый ключ CA для подписи сертификатов (в том числе и OCSP). В промежутке t1-t3 используется новый сертификат CA. И когда наступает этап t1, когда старый сертификат ещё до истечения срока обновляется на новый, то в промежутке t1-t2 может случиться следующее:

  • клиент отправляет запрос на проверку статуса сертификата Cert1 или Cert2, которые подписаны ключом CA Key 1
  • на сервере CA уже действует новый ключ CA Key 2 и, соответственно, подписанный новым ключом сертификат OCSP
  • сервер подписывает новым ключом OCSP ответ для клиента и пересылает
  • клиент сверяет подписи OCSP и проверяемого сертификата. Подписи не совпадут, т.к. сертификат подписан ключом CA Key 1, а OCSP ответ уже ключом CA Key 2 и откланяет ответ от OCSP Responder, поскольку проверяемый сертификат и сертификат подписи Online Responder должны быть подписаны одним ключом CA.

Чтобы устранить проблему на указанном отрезке времени в Windows Server 2008 включено обновление OCSP Signing сертификатов с использованием существующих ключей. По умолчанию оно не включено, поэтому для активации такого обновления в командной строке следует выполнить:

certutil –setreg ca\UseDefinedCACertInRequest 1

После выполнения этой команды должно получиться нечто похожее на:

C:\Users\administrator>certutil -setreg ca\UseDefinedCACertInRequest 1
SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\contoso-DC2-CA\UseDefine
dCACertInRequest:

New Value:
  UseDefinedCACertInRequest REG_DWORD = 1
CertUtil: -setreg command completed successfully.
The CertSvc service may need to be restarted for changes to take effect.

Как гласит сообщение, после этой процедуры следует перезапустить службу AD CS:

net stop certsvc
net start certsvc

На сегодня, пожалуй, всё, а в следующий раз продолжим с конфигурированием Online Responder и политики отзыва сертификатов.

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

$RootPoint = "D:\Users\Shared Documents"
$dest = 'E:\DestFolder'
$rep = $RootPoint.Replace("\","\\")
dir $RootPoint -Include *.msi -Recurse | %{
    $suf = $_.directory.tostring() -replace $rep
    New-Item -itemtype d -path $($dest + $suf) -force -ea 0
    copy $_ $("$dest" + "$suf")
}

Этот скрипт будет искать все MSI файлы в папке D:\Users\Shared Documents и подпапках. Если файл будет найден, то он будет скопирован в E:\SomeFolder с повторением структуры папок. Для начала я заэскейпил слеши в исходной папке. И в цикле уже отрезаю путь до корня обычным оператором –replace. После чего хвост пристыковываю к пути назначения, чтобы получить новую структуру папок и создаю нужные папки в месте назначения. И последней строкой копирую сам файл в уже подготовленную папку.

Решений для этой задачи на самом деле очень много и я постарался сделать наиболее простой вариант, для разминки мозгов, так сказать :)

Сегодня случилось то, что случилось, а именно, получил письмо с таким началом:

Dear Vadims Podans,
Congratulations! We are pleased to present you with the 2009 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others.

Если быть более кратким – я был номинирован на Microsoft MVP по программе PowerShell. Стало быть, мои усилия в блоге и форумах были оценены (по достоинству или нет – это уже судить вам, уважаемые читатели). Действительно, я отдал блогу и PowerShell'у много сил. Если немного посмотреть в историю, то мой первый пост про PowerShell был написан год назад (8 марта 2008) – PowerShell. На тот момент познаний в теме было чуть менее, чем нуль. Но благодаря поддержке Васи Гусева (http://xaegr.wordpress.com) я смог подняться до того уровня, где я сейчас и получил возможность делиться со своими знаниями с общественностью. Я очень надеюсь, что на этом моя работа с PowerShell не остановится и в блоге ещё появятся интересные статьи.

Этот статус для меня ценен ещё и тем, что я 4-й действующий MVP в Латвии:

  1. Andrejs Mamontovs – ASP/ASP.NET
  2. Valdis Iļjučonoks - Visual C#
  3. Maciej Pilecki – SQL Server
  4. Vadims Podāns - PowerShell

Быть в четвёрке по стране (хоть и совсем небольшой) это тоже позитив. Вобщем, спасибо всем, кто участвовал в моём становлении как MVP :)

По просьбе читателей, а так же с учётом востребованности (судя по сообщениям форумов и ньюсгрупп) я нашёл время переписать скрипт ShareUtils.ps1 с поддержкой работы с удалёнными машинами и попутно пофиксив недочёты, которые были найдены за время эксплуатации предыдущей версии скрипта. Предыдущая версия опубликована здесь: Управление безопасностью общих папок (сетевых шар) в PowerShell (часть 4)

Технический функционал изменился только возможностью работы с удалёнными компьютерами, но синтаксис был изменён (а так же удалены лишние функции) по аналогии с PrinterUtils и имеет примерно следующий вид:


Read more →