unable to verify the first certificate
A cadeia de certificados está incompleta.
Isso significa que o servidor da web ao qual você está se conectando está configurado incorretamente e não incluiu o certificado intermediário na cadeia de certificados que ele enviou a você.
Cadeia de certificados
Provavelmente tem a seguinte aparência:
- Certificado do servidor - armazena um certificado assinado pelo intermediário.
- Certificado intermediário - armazena um certificado assinado pela raiz.
- Certificado raiz - armazena um certificado autoassinado.
O certificado intermediário deve ser instalado no servidor, junto com o certificado do servidor.
Os certificados raiz são incorporados aos aplicativos de software, navegadores e sistemas operacionais.
O aplicativo que atende o certificado deve enviar a cadeia completa, isso significa o próprio certificado do servidor e todos os intermediários. O certificado raiz deve ser conhecido pelo cliente.
Recrie o problema
Acesse https://incomplete-chain.badssl.com usando seu navegador.
Não mostra nenhum erro (o cadeado na barra de endereço é verde).
Isso ocorre porque os navegadores tendem a completar a cadeia se não forem enviados do servidor.
Agora, conecte-se a https://incomplete-chain.badssl.com usando o 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);
});
Logs: " Erro: não é possível verificar o primeiro certificado ".
Solução
Você precisa completar a cadeia de certificados.
Fazer isso:
1: você precisa obter o certificado intermediário ausente no .pem
formato e, em seguida,
2a: estenda o armazenamento de certificados interno do Node usando NODE_EXTRA_CA_CERTS
,
2b: ou passe seu próprio pacote de certificados (intermediários e raiz) usandoca
opção
1. Como obtenho certificado intermediário?
Usando openssl
(vem com Git para Windows ).
Salve os detalhes do certificado do servidor remoto:
openssl s_client -connect incomplete-chain.badssl.com:443 -servername incomplete-chain.badssl.com | tee logcertfile
Estamos procurando o emissor (o certificado intermediário é o emissor / assinante do certificado do servidor):
openssl x509 -in logcertfile -noout -text | grep -i "issuer"
Ele deve fornecer o URI do certificado de assinatura. Baixe:
curl --output intermediate.crt http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt
Por fim, converta-o para .pem
:
openssl x509 -inform DER -in intermediate.crt -out intermediate.pem -text
2a NODE_EXTRA_CERTS
Estou usando o ambiente cruzado para definir variáveis de ambiente no package.json
arquivo:
"start": "cross-env NODE_EXTRA_CA_CERTS=\"C:\\Users\\USERNAME\\Desktop\\ssl-connect\\intermediate.pem\" node index.js"
2b. ca
opção
Essa opção substituirá as CAs raiz internas do Nó.
É por isso que precisamos criar nossa própria CA raiz. Use ssl-root-cas .
Em seguida, crie um https
agente personalizado configurado com nosso pacote de certificados (raiz e intermediário). Passe este agente para axios
ao fazer uma solicitação.
// 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);
});
Em vez de criar um https
agente personalizado e passá-lo para axios
, você pode colocar os certificados no https
agente global:
// Applies to ALL requests (whether using https directly or the request module)
https.globalAgent.options.ca = rootCas;
Recursos:
- https://levelup.gitconnected.com/how-to-resolve-certificate-errors-in-nodejs-app-involving-ssl-calls-781ce48daded
- https://www.npmjs.com/package/ssl-root-cas
- https://github.com/nodejs/node/issues/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/
- Como converter .crt para .pem