Pull to refresh

Как подписать свой первый скрипт за 48 часов

Reading time3 min
Views38K

Проблема


Когда задача, требующая решения, небольшая, совсем не хочется писать для её решения отдельную утилиту, особенно, если ты — .NET-программист.
Скрипт? Однозначно, да, но ставить на боевую машину под управлением Windows сторонний интерпретатор совсем уж не по-христиански. Так почему бы не воспользоваться Windows Powershell? Готов сразу честно признаться: практически никакого опыта с ним не было, но уж больно заманчиво выглядел.
Скрипт, решающий задачу, был готов через 15 минут, если не учесть одно «но». Скриптом пока назвать это было сложно, потому что это был набор инструкций, непригодный для выполнения в виде скрипта. Непригодный, с точки зрения PowerShell.

Всему есть разумное объяснение — конечно же, на выполнение скриптов накладываются определенные ограничения, задаваемые политикой исполнения скриптов. Создав скрипт, я не смог выполнить его тут же на своей машине. Однако проблема, решаемая для локальной машины временным изменением политики исполнения на Unrestricted или, правильнее, RemoteSigned, на рабочем сервере поднимается всерьез.

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

После двух суток мучений дома и в офисе, представляю на суд общественности краткий мануал по подписи скриптов для PowerShell.

Решение


По умолчанию, исполнение любых скриптов запрещено. Для начала, необходимо разрешить выполнение только подписанных скриптов от доверенных издателей с доверенным корневым сертификатом. В рамках сеанса администратора Powershell:

> Set-ExecutionPolicy AllSigned

Дальнейшие танцы с бубном касаются утилиты по созданию корневого и персонального сертификатов.
Все сертификаты, согласно «инструкции» по подписыванию скриптов

> Get-Help About_Signing

создаются с использованием утилиты makecert.exe, находящейся в %Program Files%\Microsoft SDKs\Windows\v7.0A\bin\makecert

Следующие два действия выполняются в рамках обычного сеанса командной строки:

> makecert -n "CN=PowerShell Local Certificate Root" -a sha1 -eku 1.3.6.1.5.5.7.3.3 -r -sv root.pvk root.cer -ss Root -sr localMachine

> makecert -pe -n "CN=PowerShell User" -ss MY -a sha1 -eku 1.3.6.1.5.5.7.3.3 -iv root.pvk -ic root.cer


Первая строка создает корневой сертификат, используя в качестве удостоверяющего центра локальную машину. Наиболее популярный «бесплатный» способ получения сертификата.
Вторая строка создает персональный сертификат пользователя PowerShell, которым будут подписываться скрипты, заверяя его корневым сертификатом. Если всё прошло успешно, обе строки должны показать результат Succeeded.

Приведенные выше манипуляции можно и не выполнять, если персональный сертификат X509 уже есть.

После этого, на всякий случай, можно проверить, что ОС в курсе насчет только что созданного сертификата. PowerShell:

> Get-Childitem cert:\CurrentUser\my -codesigning

Подписывать скрипты уже можно, но, в таком случае, на подпись скрипта каждый раз будет уходить такая строка Powershell:

> Set-AuthenticodeSignature "FileName" @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]

Было бы логичным создать скрипт, который будет подписывать другие скрипты. Скрипт нужно создавать в любом текстовом редакторе, кроме PowerShell ISE. Для скриптов, созданных внутри этой среды, возникнут проблемы с подписыванием в виде Unknown Error. Решение взято здесь.

Сам скрипт выглядит так:
param([string] $file=$(throw "Please specify a filename."))
$cert = @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]
Set-AuthenticodeSignature $file $cert

При помощи инструкций, указанных выше, подпишем сам этот скрипт в интерактивном режиме PowerShell.
После этого, скрипт для выполнения на другой машине может быть подписан так:

> .\Add-Signature.ps1 MyScript.ps1

О грустном


На любой машине, кроме той, на которой создавался сертификат:
  1. Если корневой сертификат не является доверенным, выполнить скрипт не удастся вообще.
  2. Если персональный сертификат издателя, подписавшего скрипт, не является доверенным, скрипт выполнится только с подтверждением.

Для того, чтобы добавить корневой и персональный сертификаты в доверенные, нужно воспользоваться админской консолью mmc с оснасткой Certificates. Сертификаты добавлять в папки Trusted Root Certification Authorities и Trusted Publishers.

Не претендует на роль единственно верного решения, но результаты исследований показывают, что пока это более или менее нормальный способ. Прошу знающих помочь прояснить ситуацию и ткнуть ссылкой, по возможности.
Tags:
Hubs:
Total votes 30: ↑22 and ↓8+14
Comments29

Articles