Page tree

Введение

В современной разработке обеспечение целостности и подлинности исходного кода имеет первостепенное значение. 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:

  1. Перейдите в Settings → SSH and GPG keys.
  2. Обратите внимание: для подписи коммитов по SSH в GitHub существует отдельная вкладка "Signing Keys" (не путать с обычными Authentication Keys).
  3. Нажмите New signing key, вставьте содержимое id_ecdsa_sk_git_signing.pub.
  4. Убедитесь, что email в настройках Git (git config user.email) совпадает с подтвержденным email в аккаунте GitHub.

GitLab:

  1. Перейдите в Preferences → SSH Keys.
  2. Добавьте публичный ключ. 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 гарантирует, что агент не сможет подписать данные без вашего физического подтверждения на токене.

Корпоративные сценарии и жизненный цикл ключей

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

  1. Централизованный allowed_signers: В командах рекомендуется хранить актуальный файл allowed_signers в защищенном внутреннем репозитории или на корпоративном портале. Разработчики должны синхронизировать его локально для верификации коммитов коллег.
  2. Отзыв ключа (Revocation): При утере Рутокен MFA или увольнении сотрудника администратор безопасности должен:
    • Удалить публичный ключ из систем хостинга (GitHub / GitLab).
    • Удалить запись из корпоративного файла allowed_signers.
    • Заблокировать доступ к репозиториям на уровне IAM.
  3. Ротация ключей: Поскольку используется резидентный ключ (-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 переводит контроль целостности кода на новый уровень. Это решение обеспечивает неотрекаемость действий разработчиков, защищает закрытые ключи от компрометации на уровне ОС и позволяет выстроить прозрачный, аудируемый процесс разработки, соответствующий современным требованиям информационной безопасности.

  • No labels