Как научить git доверять незнакомому CA сертификату, а не выключать верификацию SSL
20 мая 2022

Как научить git доверять незнакомому CA сертификату, а не выключать верификацию SSL

Мануал сделан под Windows, но работать должен работать и с *nix/ использовать мы будем Openssl.

Илья Зверев
Архитектор IT-решений
Собственно, так выглядит ошибка

C:\Git>git clone https://domain/gitrep/
Cloning into 'gitrep'...
fatal: unable to access 'https://domain/gitrep/': SSL certificate problem: unable to get local issuer certificate

Что нам может потребоваться из софта

  1. Cобственно git.
  2. Браузер — в статье я буду описывать вариант для chromium.
  3. Notepad++ или любой другой редактор, который аккуратно относится к кодировкам и символам переноса строк.
  4. Openssl — опционально. Можно посмотреть информацию о сертификатах.
  5. Keytool из jdk или jre, что бы прочитать файл со связкой сертификатов.


Как подтвердить ошибку


C:\Git>openssl s_client -connect domain:443
CONNECTED(00000194)
depth=0 C = XX, ST = Xxxxxx, O = Xxxxxxxxx, OU = Xxxxxxxxx, CN = xxxxxxxx
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = XX, ST = Xxxxxx, O = Xxxxxxxxx, OU = Xxxxxxxxx, CN = xxxxxxxx
verify error:num=21:unable to verify the first certificate
verify return:1
Как видим, openssl тоже ничего не знает о сертификатах. Правда, openssl и git могут смотреть на разные хранилища известных корневых сертификатов (git сам отдаст ему нужное) − ошибка не обязательно воспроизведется. Поэтому нужно отдать openssl то же самое, что отдаст ему git.

Выполняем команду в git и находим расположение хранилища доверенных сертификатов:

C:\Git\>git config --system --list
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
http.sslbackend=openssl
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge --skip -- %f
filter.lfs.process=git-lfs filter-process --skip
filter.lfs.required=true
credential.helper=manager
Мы видим, что git хранит цепочку сертификатов в файле C:\Program Files\Git\mingw64\ssl\certsca-bundle.crt

Проверим, что выдаст openssl:

C:\Git>openssl s_client -connect domain:443 -CAfile C:\Program Files\Git\mingw64\ssl\certs\ca-bundle.crt
CONNECTED(00000194)
depth=0 C = XX, ST = Xxxxxx, O = Xxxxxxxxx, OU = Xxxxxxxxx, CN = xxxxxxxx
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = XX, ST = Xxxxxx, O = Xxxxxxxxx, OU = Xxxxxxxxx, CN = xxxxxxxx
verify error:num=21:unable to verify the first certificate
verify return:1
Мы убедились — openssl не может подтвердить git корректность сертификатов, т.к. не знает корневого издателя сертификата.

При желании мы можем сами прочитать, что лежит в ca-bundle.crt используя keytool. Т.к. выдача будет длинная, сразу стоит отправить её в текстовый файл:

C:\Git>keytool -printcert -v -file C:\Program Files\Git\mingw64\ssl\certs\ca-bundle.crt > certs_info.txt
Начало файла будет выглядеть приблизительно так:

Certificate[1]:
Owner: C=ES, O=ACCV, OU=PKIACCV, CN=ACCVRAIZ1
Issuer: C=ES, O=ACCV, OU=PKIACCV, CN=ACCVRAIZ1
Serial number: 5ec3b7a6437fa4e0
Valid from: Thu May 05 13:37:37 MSK 2011 until: Tue Dec 31 12:37:37 MSK 2030
Certificate fingerprints:
         MD5:  D0:A0:5A:EE:05:B6:09:94:21:A1:7D:F1:B2:29:82:02
         SHA1: 93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17
         SHA256: 9A:6E:C0:12:E1:A7:DA:9D:BE:34:19:4D:47:8A:D7:C0:DB:18:22:FB:07:1D:F1:29:81:49:6E:D1:04:38:41:13
Signature algorithm name: SHA1withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3

Extensions:
...

В файле будет весь список CA сертификатов, которым git доверяет.


Как сделать так, что бы git начал доверять CA сертификату сервера

Подготовим CA сертификат нашего https репозитория к дальнейшему использованию:

  1. Заходим браузером на адрес, и вне зависимости от того, выдает он ошибку подключения или нет, открываем на просмотр сертификат.
  2. Переходим на вкладку с цепочкой сертификации и ищем CA сертификат (самый верхний в цепочке). Открываем его на просмотр.
  3. Переходим на вкладку Details/Состав для CA сертификата. Нажимаем кнопку Copy to File/Копировать в файл в мастере выбираем X.509 (.CER) в Base64 кодировке. Сохраняем файл, например, с названием ca.crt.
Альтернативно можно выгрузить его с помощью openssl, т.к. в его выдаче при выполнении подключения мы получаем сертификат сервера (или цепочку сертификатов). Cохранив их в файл .cer, можно с помощью оснастки так же найти корневой сертификат.


Подготавливаем цепочку доверенных сертификатов к изменению

Выполняем команду в git и находим расположение хранилища доверенных сертификатов:

Ранее мы уже нашли, где git хранит свою цепочку доверенных ssl CA сертификатов: C:\ProgramFiles\Git\mingw64\ssl\certs

Мне не понравилась папка, в которой расположен текущий. Поэтому я переместил файл и затем указал новый путь командой:

git config --system http.sslcainfo C:/Git/_certs/ca-bundle.crt
Если вы не являетесь администратором машины или хотите сохранить изменения только для себя, команда немного изменится:

git config --global http.sslcainfo C:/Git/_certs/ca-bundle.crt
Важно! По-хорошему, папка, в которой должна храниться цепочка, должна быть недоступна для редактирования никому, кроме администратора машины. В целях безопасности. Поэтому перемещение — опционально, и только если вы понимаете, что делаете.

Теперь открываем текстовым редактором (крайне желательно — не notepad! и желательно — делайте резервные копии!) наш ca-bundle.crt и видим сертификаты:

-----BEGIN CERTIFICATE-----
куча символов в Base64
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
еще одна куча
-----END CERTIFICATE-----
...
Открываем файл ca.crt и извлекаем из него текст нашего CA сертификата.

Аккуратно копируем сертификат из ca.crt в конец файла ca-bundle.crt так, чтобы не сломать структуру файла, и сохраняем.

Можем убедиться, что все ок, последовательно, теми же командами, что помогли локализовать ошибку:

C:\Git>keytool -printcert -v -file C:\Git\_certs\ca-bundle.crt > certs_info.txt
В конце файла последним мы должны увидеть данные нашего добавленного сертификата.

Далее убедимся, что openssl не выдаст больше ошибку о том, что не может подтвердить ssl сертификат сервера:

C:\Git>openssl s_client -connect domain:443 -CAfile C:\Git\_certs\ca-bundle.crt
CONNECTED(00000194)
depth=0 C = XX, ST = Xxxxxx, O = Xxxxxxxxx, OU = Xxxxxxxxx, CN = xxxxxxxx
verify return:1
depth=0 C = XX, ST = Xxxxxx, O = Xxxxxxxxx, OU = Xxxxxxxxx, CN = xxxxxxxx
verify return:1
Ошибки исправлены — теперь нужно снова попробовать склонировать git-репозиторий.

PROFIT! ;)


Если было полезно, подписывайтесь на наши каналы с экспертными материалами:

Youtube >
Telegram >
Вам также может быть интересно