unable to verify the first certificate
Ланцюг сертифікатів неповний.
Це означає, що веб-сервер, до якого ви підключаєтесь, неправильно налаштований і не включив проміжний сертифікат у ланцюжок сертифікатів, який він надіслав вам.
Ланцюг сертифікатів
Це, швидше за все, виглядає так:
- Сертифікат сервера - зберігає сертифікат, підписаний проміжним.
- Проміжний сертифікат - зберігає сертифікат, підписаний коренем.
- Root сертифікат - зберігає самопідписаний сертифікат.
Проміжний сертифікат повинен бути встановлений на сервері разом із сервером.
Кореневі сертифікати вбудовані в програмні програми, браузери та операційні системи.
Додаток, що обслуговує сертифікат, повинен надіслати повний ланцюг, це означає сам сертифікат сервера та всі проміжні продукти. Корінний сертифікат повинен бути відомий клієнтом.
Відтворити проблему
Перейдіть на сторінку https://incomplete-chain.badssl.com за допомогою свого браузера.
Він не відображає помилок (замок в адресному рядку зелений).
Це тому, що браузери, як правило, завершують ланцюг, якщо він не надсилається з сервера.
Тепер підключіться до https://incomplete-chain.badssl.com за допомогою Node:
// index.js
const axios = require('axios');
axios.get('https://incomplete-chain.badssl.com')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Журнали: " Помилка: неможливо підтвердити перший сертифікат ".
Рішення
Потрібно самостійно заповнити ланцюжок сертифікатів.
Для цього:
1:.pem
Тоді вам потрібно отримати пропущений проміжний сертифікат у форматі
2а: розширити вбудований сховище Node за допомогою NODE_EXTRA_CA_CERTS
,
2b: або передайте власний пакет сертифікатів (проміжні та кореневі), використовуючи ca
опцію.
1. Як отримати проміжний сертифікат?
Використання openssl
(поставляється з Git для Windows ).
Збережіть дані сертифікатів віддаленого сервера:
openssl s_client -connect incomplete-chain.badssl.com:443 -servername incomplete-chain.badssl.com | tee logcertfile
Ми шукаємо емітента (проміжний сертифікат - це емітент / підписант серверного сертифіката):
openssl x509 -in logcertfile -noout -text | grep -i "issuer"
Він повинен дати вам URI сертифіката підписання. Завантажте його:
curl --output intermediate.crt http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt
Нарешті, перетворіть його на .pem
:
openssl x509 -inform DER -in intermediate.crt -out intermediate.pem -text
2а. NODE_EXTRA_CERTS
Я використовую крос-env для встановлення змінних середовища у package.json
файлі:
"start": "cross-env NODE_EXTRA_CA_CERTS=\"C:\\Users\\USERNAME\\Desktop\\ssl-connect\\intermediate.pem\" node index.js"
2б. ca
варіант
Ця опція буде замінена вбудованими кореневими ЦЗ у вузлі.
Ось чому нам потрібно створити власний корінь CA. Використовуйте ssl-root-cas .
Потім створіть спеціальний https
агент, налаштований з нашим пакетом сертифікатів (кореневим та проміжним). Передайте цього агента, axios
коли ви робите запит.
// index.js
const axios = require('axios');
const path = require('path');
const https = require('https');
const rootCas = require('ssl-root-cas').create();
rootCas.addFile(path.resolve(__dirname, 'intermediate.pem'));
const httpsAgent = new https.Agent({ca: rootCas});
axios.get('https://incomplete-chain.badssl.com', { httpsAgent })
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Замість того, щоб створити спеціальний https
агент і передати його axios
, ви можете розмістити сертифікати на https
глобальному агенті:
// Applies to ALL requests (whether using https directly or the request module)
https.globalAgent.options.ca = rootCas;
Ресурси:
- https://levelup.gitconnected.com/how-to-resolve-certificate-errors-in-nodejs-app-involving-ssl-calls-781ce48dadeded
- https://www.npmjs.com/package/ssl-root-cas
- https://github.com/nodejs/node/isissue/16336
- https://www.namecheap.com/support/knowledgebase/article.aspx/9605/69/how-to-check-ca-chain-installation
- /superuser/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file/
- Як перетворити .crt в .pem