SSL сертификаты больше не работают с cURL

Вопрос или проблема

При выполнении следующей команды в WSL:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh

Я получаю следующую ошибку:

curl: (60) Проблема с SSL-сертификатом: не удалось получить локальный сертификат-источник
Более подробная информация здесь: https://curl.haxx.se/docs/sslcerts.html

curl не смог подтвердить законность сервера и, следовательно, не смог
установить с ним защищенное соединение. Чтобы узнать больше об этой ситуации и
о том, как это исправить, пожалуйста, посетите веб-страницу, указанную выше.

Эта команда раньше выполнялась успешно, но сейчас нет. Это решение не работает, ни одна комбинация sudo apt update, sudo apt install ca-certificates --reinstall или sudo update-ca-certificates --fresh не помогает. Я перепробовал множество решений в интернете, и ни одно из них не сработало. Я пытался переустановить Ubuntu и даже установить другую версию Ubuntu, ни одно из них не сработало. Я не знаю, что пробовать дальше.

curl -k https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh

Опция -k (также известная как --insecure) пропустит проверку TLS-сертификата.

Нашел решение! У меня нет полного понимания проблемы, но я думаю, что дело в том, что корпоративная IT-служба установила некоторые сертификаты на мой компьютер с Windows, которые не были автоматически перенесены в WSL. В любом случае, проблему можно легко исправить с помощью этого скрипта PowerShell:

$StoreToDir = "all-certificates"
$CertExtension = "pem" # используйте "crt" для работы в системах Windows
$InsertLineBreaks=1

If (Test-Path $StoreToDir) {
    $path = "{0}\*" -f $StoreToDir
    Remove-Item $StoreToDir -Recurse -Force
}
New-Item $StoreToDir -ItemType directory

# Если вы хотите фильтровать по назначению сертификата (например, для языков, не зависящих от соответствия, предоставления сертификатов аутентификации сервера: "(1.3.6.1.5.5.7.3.1)"), просто добавьте:
# -and -not $_.Archived -and ( $_.EnhancedKeyUsageList -match '(1.3.6.1.5.5.7.3.1)' -or -not $_.EnhancedKeyUsageList )
Get-ChildItem -Recurse cert: `
  | Where-Object { $_ -is [System.Security.Cryptography.X509Certificates.X509Certificate2] -and $_.NotAfter.Date -gt (Get-Date).Date } `
  | ForEach-Object {

    # Запись информации о сертификате (например, для CSV, содержащего метаданные); Журнал информации с полными именами и дополнительными значениями для справки
    Write-Output "$($_.Thumbprint);$($_.GetSerialNumberString());$($_.Archived);$($_.GetExpirationDateString());$($_.EnhancedKeyUsageList);$($_.GetName())"

    # Добавление "Thumbprint" сертификата для уникальных имен файлов
    $name = "$($_.Thumbprint)--$($_.Subject)" -replace '[\W]', '_'
    $max = $name.Length

    # Уменьшаем длину, чтобы избежать ошибок файловой системы
    if ($max -gt 150) { $max = 150 }
    $name = $name.Substring(0, $max)

    # Формируем путь
    $path = "{0}\{1}.{2}" -f $StoreToDir,$name,$CertExtension
    if (Test-Path $path) { continue } # продолжаем, если сертификат уже был записан

    $oPem=new-object System.Text.StringBuilder
    [void]$oPem.AppendLine("-----BEGIN CERTIFICATE-----")
    [void]$oPem.AppendLine([System.Convert]::ToBase64String($_.RawData,$InsertLineBreaks))
    [void]$oPem.AppendLine("-----END CERTIFICATE-----")

    $oPem.toString() | add-content $path
  }

У меня была эта проблема с gcloud и curl. Для меня ответ jhud в основном исправил gcloud, но мне пришлось выполнить несколько дополнительных шагов. Чтобы заставить curl работать, мне нужно было сделать еще пару шагов после этого.

Добавьте pem файлы в центр сертификации

  1. Создайте резервную копию существующих сертификатов в /etc/ssl/certs.
  2. Переместите pem файлы, сгенерированные скриптом jhud, в /etc/ssl/certs (или, скорее, сделайте /etc/ssl/certs мягкой ссылкой на каталог, где находились pem файлы).
  3. Обновите сертификаты.
    • На Redhat: update-ca-trust
    • На других дистрибутивах: update-ca-certificates или, возможно, что-то другое.

Хотя это исправило gcloud, это не исправило curl. Чтобы заставить curl работать, я выполнил еще несколько шагов.

Укажите curl на новые pem файлы

  1. Создайте мягкие ссылки на каждый из pem файлов с именами: <hash>.0 в соответствии с ответом на stackoverflow.

    Пример:

     for pem in $pem_dir/*.pem
     do
         ln -s "$pem" "$pem_dir/$(openssl x509 -hash -noout -in "$pem").0"
     done
    
  2. Укажите curl на эти мягкие ссылки, используя аргумент --capath <pem_dir>.

Примечание: Чтобы вам не пришлось каждый раз вводить --capath <pem_dir> при запуске curl, вы можете добавить его в ваш .curlrc:

capath = <pem_dir>

Ответ или решение

Проблема с SSL-сертификатами при использовании curl в WSL (Windows Subsystem for Linux) может быть связана с отсутствием необходимых сертификатов в хранилище. Давайте разберем шаги, которые помогут решить эту проблему.

Шаг 1: Установка необходимых пакетов

Прежде всего, убедитесь, что у вас установлены пакеты ca-certificates и curl. Выполните команды:

sudo apt update
sudo apt install ca-certificates curl

Шаг 2: Обновление сертификатов

После установки или переустановки пакета ca-certificates выполните обновление сертификатов:

sudo update-ca-certificates

Шаг 3: Перенос сертификатов с Windows

Если ваша проблема сохраняется, возможно, это связано с тем, что корпоративные сертификаты, установленные на Windows, не видны в WSL. В этом случае можно использовать PowerShell скрипт для переноса сертификатов. Вот как это сделать:

  1. Откройте PowerShell от имени администратора и выполните следующий скрипт:
$StoreToDir = "all-certificates"
$CertExtension = "pem"
$InsertLineBreaks=1

If (Test-Path $StoreToDir) {
    $path = "{0}\*" -f $StoreToDir
    Remove-Item $StoreToDir -Recurse -Force
}
New-Item $StoreToDir -ItemType directory

Get-ChildItem -Recurse cert: | Where-Object { $_ -is [System.Security.Cryptography.X509Certificates.X509Certificate2] -and $_.NotAfter.Date -gt (Get-Date).Date } | ForEach-Object {
    $name = "$($_.Thumbprint)--$($_.Subject)" -replace '[\W]', '_'
    $max = $name.Length
    if ($max -gt 150) { $max = 150 }
    $name = $name.Substring(0, $max)

    $path = "{0}\{1}.{2}" -f $StoreToDir,$name,$CertExtension
    if (Test-Path $path) { continue }

    $oPem=new-object System.Text.StringBuilder
    [void]$oPem.AppendLine("-----BEGIN CERTIFICATE-----")
    [void]$oPem.AppendLine([System.Convert]::ToBase64String($_.RawData,$InsertLineBreaks))
    [void]$oPem.AppendLine("-----END CERTIFICATE-----")

    $oPem.toString() | add-content $path
}

Этот скрипт создаст папку all-certificates и сохранит в ней все сертификаты в формате pem.

Шаг 4: Перемещение сертификатов в WSL

Теперь необходимо перенести сгенерированные файлы pem в директорию /etc/ssl/certs вашей системы WSL:

  1. Перенесите файлы pem из all-certificates в /etc/ssl/certs.

    sudo cp /path/to/all-certificates/*.pem /etc/ssl/certs/
  2. После этого обновите сертификаты снова:

    sudo update-ca-certificates

Шаг 5: Создание символических ссылок для сертификатов

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

pem_dir="/etc/ssl/certs"
for pem in $pem_dir/*.pem; do
    ln -s "$pem" "$pem_dir/$(openssl x509 -hash -noout -in "$pem").0"
done

Шаг 6: Настройка curl (опционально)

Чтобы не указывать --capath при каждом вызове curl, добавьте следующую строку в файл ~/.curlrc:

capath = /etc/ssl/certs

Заключение

После выполненных шагов проблема с SSL-сертификатами должна быть решена, и команда curl должна работать корректно. Если же проблема все еще сохраняется, рассмотрите возможность использования флага -k (т.е. --insecure), но это не рекомендуется для продакшн-среды, так как оно отключает проверку сертификатов безопасности.

Оцените материал
Добавить комментарий

Капча загружается...