Введение
В современной разработке обеспечение целостности и подлинности исходного кода имеет первостепенное значение. Git позволяет криптографически подтвердить, что изменения были внесены доверенным автором. Использование аппаратного токена (Рутокен MFA) с поддержкой FIDO2 для хранения SSH-ключей подписи дает следующие преимущества:
- Неотрекаемость (Non-Repudiation): Криптографическое доказательство того, что изменения внесены владельцем токена.
- Аппаратная защита: Закрытый ключ никогда не покидает пределы Рутокен MFA, что защищает его от компрометации через вредоносное ПО на рабочей станции.
- Гарантия присутствия пользователя: Каждая операция подписи требует физического подтверждения (касания/ввода PIN), что исключает фоновое или автоматическое подписание злоумышленником.
- Упрощение управления ключами: Использование SSH-ключей для подписи избавляет от необходимости поддерживать сложную инфраструктуру GPG-серверов.
- Подтверждение подлинности на GitHub и GitLab — коммиты могут отображаться со статусом Verified.
Данная инструкция описывает настройку Git для использования SSH/FIDO2-ключей на аппаратном токене Рутокен MFA при подписании коммитов и тегов.
Предварительные требования
Необходимо наличие:
- Аппаратного токена с поддержкой FIDO2/WebAuthn (Рутокен MFA).
- Git версии 2.34 или новее.
Проверка версии:
git --version
- OpenSSH версии:
- OpenSSH 8.2 или новее — базовая поддержка FIDO2 SSH-ключей.
- OpenSSH 8.3 или новее — поддержка параметра -O verify-required.
Проверка версии:
ssh -V
- Настроенного PIN-кода FIDO2 на токене (рекомендуется для resident-ключей).
Пошаговая настройка
Шаг 1. Создание выделенного SSH-ключа для подписи
Рекомендуется создавать отдельный ключ именно для подписи коммитов, чтобы разделить контексты аутентификации и криптографического подтверждения авторства.
Для Linux / macOS:
ssh-keygen -t ecdsa-sk -O resident -O verify-required \ -C "Git signing key $(git config user.email)" \ -f ~/.ssh/id_ecdsa_sk_git_signing
Для Windows (PowerShell):
ssh-keygen -t ecdsa-sk -O resident -O verify-required ` -C "Git signing key" ` -f "$env:USERPROFILE\.ssh\id_ecdsa_sk_git_signing"
Разбор критически важных параметров:
- -t ecdsa-sk — создание FIDO2-ключа ECDSA (оптимально для совместимости с профилями Рутокен MFA).
- -O resident — (Рекомендуется) создание резидентного ключа. Идентификатор ключа (key handle) хранится на самом токене. Это позволяет использовать ключ на разных рабочих станциях без необходимости экспорта/импорта файлов.
- -O verify-required — (Рекомендуется) явное требование подтверждения пользователя (User Presence / User Verification) при каждой операции подписи.
Шаг 2. Настройка Git
Указываем Git, что теперь для подписи используется формат SSH, а не GPG.
# Переключаем формат подписи на SSH git config --global gpg.format ssh
Указываем путь к публичному ключу (именно к .pub файлу!)
Для Linux / macOS:
git config --global user.signingkey ~/.ssh/id_ecdsa_sk_git_signing.pub
Для Windows (PowerShell):
git config --global user.signingkey "$env:USERPROFILE\.ssh\id_ecdsa_sk_git_signing.pub"
Включаем автоматическую подпись коммитов и аннотированных тегов
git config --global commit.gpgsign true git config --global tag.forceSignAnnotated true
Шаг 3. Настройка файла доверенных подписантов (allowed_signers)
Для локальной верификации подписей Git использует файл allowed_signers, который связывает email автора с его публичным ключом.
Создание файла: Linux / macOS:
mkdir -p ~/.ssh touch ~/.ssh/allowed_signers
Windows (PowerShell):
$sshDir = "$env:USERPROFILE\.ssh"
if (-not (Test-Path $sshDir)) { New-Item -Path $sshDir -ItemType Directory }
New-Item -Path "$sshDir\allowed_signers" -ItemType File -Force
notepad "$sshDir\allowed_signers"
Заполнение файла: Откройте allowed_signers и добавьте строку в следующем формате:
user@example.com namespaces="git" sk-ecdsa-sha2-nistp256@openssh.com AAAAInNr... [остальная часть публичного ключа] Git signing key
Важно: Указание namespaces="git" критично. Оно ограничивает область действия ключа только подписью Git-коммитов, предотвращая его случайное использование для SSH-аутентификации на серверах.
Указываем Git путь к этому файлу:
Linux / macOS:
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
Windows (PowerShell):
git config --global gpg.ssh.allowedSignersFile "$env:USERPROFILE\.ssh\allowed_signers"
Шаг 4. Подписание и локальная верификация
Теперь при каждом коммите Рутокен MFA запросит подтверждение.
Создание подписанного коммита и тега:
git commit -S -m "Secure commit message" git tag -s v1.0.0 -m "Release 1.0.0"
Проверка подписей:
git log --show-signature -1 git show --show-signature <commit_hash> git tag -v <tag_name>
Ожидаемый результат:
Good "git" signature for user@example.com
Шаг 5. Достижение статуса "Verified" на GitHub и GitLab
Чтобы платформа хостинга кода отображала зеленый бейдж Verified, публичный ключ должен быть зарегистрирован в профиле.
GitHub:
- Перейдите в Settings → SSH and GPG keys.
- Обратите внимание: для подписи коммитов по SSH в GitHub существует отдельная вкладка "Signing Keys" (не путать с обычными Authentication Keys).
- Нажмите New signing key, вставьте содержимое id_ecdsa_sk_git_signing.pub.
- Убедитесь, что email в настройках Git (git config user.email) совпадает с подтвержденным email в аккаунте GitHub.
GitLab:
- Перейдите в Preferences → SSH Keys.
- Добавьте публичный ключ. GitLab автоматически использует его как для аутентификации, так и для верификации подписей коммитов.
Особенности использования SSH Agent и FIDO2
Вы можете добавить хэндл ключа в ssh-agent, чтобы не указывать путь к файлу вручную.
Для Linux / macOS:
ssh-add ~/.ssh/id_ecdsa_sk_git_signing
Для Windows (PowerShell):
ssh-add "$env:USERPROFILE\.ssh\id_ecdsa_sk_git_signing"
Примечание по безопасности:
Файл, который вы добавляете в агент (id_ecdsa_sk_git_signing), — это не закрытый ключ, а лишь хэндл-ссылка на криптографический объект внутри Рутокен MFA.
- ssh-agent не кэширует PIN-код FIDO2.
- Флаг -O verify-required гарантирует, что агент не сможет подписать данные без вашего физического подтверждения на токене.
Корпоративные сценарии и жизненный цикл ключей
При внедрении практики подписи коммитов в организации необходимо учитывать жизненный цикл ключей:
- Централизованный allowed_signers: В командах рекомендуется хранить актуальный файл allowed_signers в защищенном внутреннем репозитории или на корпоративном портале. Разработчики должны синхронизировать его локально для верификации коммитов коллег.
- Отзыв ключа (Revocation): При утере Рутокен MFA или увольнении сотрудника администратор безопасности должен:
- Удалить публичный ключ из систем хостинга (GitHub / GitLab).
- Удалить запись из корпоративного файла allowed_signers.
- Заблокировать доступ к репозиториям на уровне IAM.
- Ротация ключей: Поскольку используется резидентный ключ (-O resident), "скопировать" его нельзя. Ротация подразумевает генерацию нового ключа на новом (или том же) токене и обновление публичных частей во всех системах верификации.
Устранение неисправностей (Troubleshooting)
- Ошибка: agent refused operation / sign_and_send_pubkey: signing failed
Решение: Сбросьте агент и добавьте ключ заново:
ssh-add -D ssh-add ~/.ssh/id_ecdsa_sk_git_signing
- Ошибка: No principal matched / error: gpg.ssh.allowedSignersFile needed...
Решение: Проверьте, что email в allowed_signers побуквенно совпадает с git config user.email. Убедитесь, что указан параметр namespaces="git".
Проблема: В Windows команда ssh-add не работает.
Решение: Убедитесь, что служба запущена. Проверьте её состояние командой Get-Service ssh-agent (при необходимости запустите её командой Start-Service ssh-agent).
- Проблема: GitHub / GitLab не отображают статус Verified.
Решение: Проверьте, что ключ добавлен именно в раздел Signing Keys (для GitHub), а email коммиттера (git config user.email) верифицирован в профиле разработчика на платформе.
Заключение
Использование SSH-подписей Git совместно с Рутокен MFA переводит контроль целостности кода на новый уровень. Это решение обеспечивает неотрекаемость действий разработчиков, защищает закрытые ключи от компрометации на уровне ОС и позволяет выстроить прозрачный, аудируемый процесс разработки, соответствующий современным требованиям информационной безопасности.