Как стать автором
Поиск
Написать публикацию
Обновить

Автоматическая выдача сертификатов пользователям через GPO

Уровень сложностиПростой
Время на прочтение4 мин
Количество просмотров2.3K

Введение

В корпоративной среде с ростом количества сотрудников, которым требуется доступ к системам с использованием ЭЦП, возникла необходимость автоматизировать процесс установки сертификатов.

Попытки применить стандартные средства — Import-PfxCertificatecertutil и другие — результата не дали: сертификаты не виделись рядом приложений, включая СБИС. Готовых рабочих решений тоже не нашлось. Пришлось разрабатывать собственный метод.

В этой статье описан механизм, применяемый для распространения сертификатов ИФНС. Методы экспорта ключей и сертификатов можно найти в сети, поэтому они здесь не рассматриваются. Вопросы безопасности при передаче приватных ключей также остаются за рамками — предполагается, что всё выполняется во внутреннем доверенном контуре.

За основу была взята статья «Перенос контейнеров закрытых ключей и сертификатов CryptoPro», где описан ручной процесс. Я доработал его и автоматизировал для централизованного распространения через GPO.


Проблема

При переносе сертификатов и ключей между машинами или профилями возникает одна и та же трудность: они «привязаны» к SID пользователя.

Если импортировать .reg напрямую, записи окажутся связаны с SID другого пользователя и работать не будут.

Поэтому при автоматическом распространении необходимо корректно подставлять текущий SID.


Решение

Я подготовил набор PowerShell-скриптов, которые выполняются от имени пользователя при логоне (через GPO Logon Script).

Сценарий работы такой:

  1. Шаблон реестра
    В исходном .reg файле хранится конфигурация с «старым» SID.

  2. Подмена SID
    Скрипт получает SID текущего пользователя

    [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value
    

    и заменяет им статический идентификатор в файле.

  3. Импорт реестра
    Обновлённый .reg файл импортируется в HKCU.

  4. Копирование сертификатов
    Из сетевой папки (\\share\Cert\My) копируются нужные файлы в профиль пользователя:

    %APPDATA%\Microsoft\SystemCertificates\My

  5. Готово
    При следующем запуске приложений (Outlook, браузеры, CryptoPro) пользователь сразу получает доступ к сертификатам.


Пример кода

Запуск разных скриптов по группам

Этот пример показывает, как можно привязывать разные сценарии к членству пользователя в группах AD. Каждое группа соответствует отдельному сертификату.

# Задаем группы и соответствующие пути к скриптам для каждой группы
$groupScriptMap = @{
    "First Group" = "\\path\first_script.ps1"
    "Second Group" = "\\path\second_script.ps1"
}

# Получаем информацию о текущем пользователе
$user = [System.Security.Principal.WindowsIdentity]::GetCurrent()

$userGroups = $user.Groups | ForEach-Object { 
    $_.Translate([System.Security.Principal.NTAccount]).Value.Split("\")[1]
}

# Перебираем каждую группу из маппинга и проверяем, состоит ли в ней пользователь
foreach ($group in $groupScriptMap.Keys) {
    if ($userGroups -contains $group) {
        Write-Output "Пользователь $($user.Name) принадлежит группе $group."
        
        # Получаем путь к скрипту для этой группы
        $scriptPath = $groupScriptMap[$group]
        Write-Output "Запускается скрипт для группы: $scriptPath"
        
        # Выполняем соответствующий скрипт
        try {
            #Start-Process -FilePath "powershell.exe" -ArgumentList "-ExecutionPolicy Bypass -File $scriptPath" -NoNewWindow -Wait
            Start-Process -FilePath "powershell.exe" -ArgumentList "-ExecutionPolicy", "Bypass", "-File", "`"$scriptPath`"" -NoNewWindow -Wait

        } catch {
            Write-Output "Ошибка при выполнении скрипта для группы $[group]: $_"
        }
    } else {
        Write-Output "Пользователь $($user.Name) не состоит в группе $group."
    }
}
 

Данные скрипт производит основные действия по замене SID, импорте reg файла и копировании хранилища личных сертификатов пользователя

 # Указываем путь к файлу реестра (исходный шаблон .reg файл)
$regFileSource = "\\path\first_file.reg"

# Определяем временную папку текущего пользователя
$tempFolder = [System.IO.Path]::GetTempPath()

# Определяем SID текущего пользователя
$userSID = (Get-WmiObject -Class Win32_UserAccount -Filter "Name='$env:USERNAME'").SID

# Определяем целевой файл во временной папке
$regFileTemp = Join-Path $tempFolder "modified_registry.reg"

# Читаем содержимое исходного файла реестра
$regContent = Get-Content -Path $regFileSource -Encoding Unicode

# Статический SID, который будем заменять
$oldSID = "S-1-5-21-3734670798-76392145-1373982661-1117"

# Заменяем статический SID на SID текущего пользователя
$updatedContent = $regContent -replace $oldSID, $userSID

# Записываем обновленный файл реестра во временную папку
$updatedContent | Out-File -FilePath $regFileTemp -Encoding Unicode

# Импортируем обновленный файл реестра
reg import $regFileTemp

# Указываем сетевую папку для копирования
$networkFolder = "\\path\My"

# Папка пользователя, куда нужно скопировать сетевую папку
$userFolder = "C:\Users\$env:USERNAME\AppData\Roaming\Microsoft\SystemCertificates"

# Копируем содержимое с заменой конфликтов
Copy-Item -Path $networkFolder -Destination $userFolder -Recurse -Force

Write-Host "Файл реестра был успешно импортирован, и папка скопирована."
 

Варианты использования

  • Распространение сертификатов ЭЦП среди сотрудников

  • Миграция рабочих мест и перенос профилей


Репозиторий

Исходный код доступен здесь. Там же постарался создать подробный и понятный README.
👉 GitHub — provision_of_certificates_GPO


Заключение

Предложенный метод позволяет автоматизировать раздачу сертификатов через GPO без ручных действий. Он прост в реализации.

При этом стоит помнить о недостатках:

  • нет централизованного контроля за сроком действия сертификатов;

  • приватные ключи передаются в файлах, что требует доверенной среды;

  • метод рассчитан именно на Windows-среду с CryptoPro.

Теги:
Хабы:
+2
Комментарии12

Публикации

Ближайшие события