No se puede verificar la firma de la hoja


142

Estoy usando node.js request.js para llegar a una API. Me sale este error

[Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE]

Todas mis credenciales son precisas y válidas, y el servidor está bien. Hice la misma solicitud con el cartero.

request({
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});

Este código solo se ejecuta en un script ejecutable ej. node ./run_file.js, ¿Es esa la razón de? ¿Necesita ejecutarse en un servidor?


Esta es una posibilidad remota, pero ¿podría ser que la API no reconoce el agente de usuario que está pasando su programa de nodo?
Héctor Correa


@HectorCorrea Pude leer la API en cartero perfectamente. ¿Por qué el nodo no puede hacerlo? Intenté cambiar el agente de usuario, no tuve suerte.
ThomasReggi

Respuestas:


157

Nota : lo siguiente es peligroso y permitirá que el contenido de la API sea interceptado y modificado entre el cliente y el servidor.

Esto también funcionó

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';


22
Actualicé esto, y gracias por responder, pero es activamente perjudicial para su seguridad. Debe agregar la CA que falta según la respuesta de @ CoolAJ86 a continuación.
mikemaccana

44
Estoy usando el complemento NodeJS llamado nodemailery nodemailer-smtp-transportfuncionó el mismo comando general. Necesita agregar esto a su createTransportobjeto:tls:{rejectUnauthorized: false}
LukeP

3
Sin embargo, @LukeP es igualmente inseguro con nodemailer. Hay una idea en el nombre: si de algo Un autorizada, por lo general quiere rechazarlo, por definición. Lo que necesita es encontrar una manera de autorizarlo correctamente (configurando los certificados de CA correctamente, como ya han dicho otras respuestas).
Bruno

@Bruno Estoy de acuerdo, debe configurarlo de la manera correcta con los certificados. Simplemente quería configurar una prueba rápida para una demostración, por lo que el código que publiqué es una solución rápida. Debería haber precedido con eso en mi comentario.
LukeP

1
@mikemaccana No hay ningún problema de seguridad si la solicitud está en el mismo servidor y usted es el único propietario.
Binar Web

89

No es un problema con la aplicación, sino con el certificado firmado por una CA intermediaria. Si acepta ese hecho y aún desea continuar, agregue lo siguiente para solicitar opciones:

rejectUnauthorized: false

Solicitud completa:

request({
    "rejectUnauthorized": false,
    "url": domain+"/api/orders/originator/"+id,
    "method": "GET",
    "headers":{
        "X-API-VERSION": 1,
        "X-API-KEY": key
    },
}, function(err, response, body){
    console.log(err);
    console.log(response);
    console.log(body);
});

Tengo este problema ahora mismo en el trabajo. Envié un ticket de TI informándoles que SSL puede estar mal configurado, me dijeron que estaba loco. ¿Hay más información que pueda darles para resolver este problema?
blakev

Esto no es realmente correcto: como mencionan CoolAJ86 y hectorcorrea, el certificado es válido, pero está firmado por una CA intermediaria.
mikemaccana

80

La solución segura

En lugar de desactivar la seguridad, puede agregar los certificados necesarios a la cadena. Primero instale el paquete ssl-root-cas desde npm:

npm install ssl-root-cas

Este paquete contiene muchos certificados intermedios en los que los navegadores confían pero el nodo no.

var sslRootCAs = require('ssl-root-cas/latest')
sslRootCAs.inject()

Agregará los certificados faltantes. Vea aqui para mas informacion:

https://git.coolaj86.com/coolaj86/ssl-root-cas.js

Además, vea la siguiente respuesta a continuación


2
¿El cliente Http no utiliza el almacén de certificados de Windows Trusted Root Certification Authority?
Richard Collette

1
El nodo utiliza los certificados de Mozilla incluidos en el binario y los anula cada vez que proporciona su propia camatriz. No sé si su módulo http también mirará a la cadena del sistema operativo. Sin embargo, curl en OS X parece usar solo la cadena del sistema operativo y no permitir certificados especificados manualmente.
coolaj86

¿Esto tiene que ejecutarse para cada proceso o puedo ejecutarlo una vez y actualizar mis certificados a nivel mundial?
Joshua Snider

Los certificados se almacenan en potencialmente dos lugares: (1) integrado en el binario node.js (2) el almacén de claves del sistema operativo. Si sus certificados están desactualizados, deberá incluir esto en su código de ejecución. No cambia el nodo binario ni su sistema operativo, solo la carpeta del proyecto.
coolaj86

1
@Sunkas Es exactamente lo que dicen los mensajes de error. No sé cómo explicarlo más simple. Es un archivo de solo lectura y no se puede editar.
coolaj86

45

La solución de CoolAJ86 es correcta y no compromete su seguridad, como deshabilitar todas las comprobaciones usando rejectUnauthorizedo NODE_TLS_REJECT_UNAUTHORIZED. Aún así, es posible que deba inyectar un certificado de CA adicional explícitamente.

Primero probé las CA raíz incluidas en el módulo ssl-root-cas :

require('ssl-root-cas/latest')
  .inject();

Todavía terminé con el UNABLE_TO_VERIFY_LEAF_SIGNATUREerror. Luego descubrí quién emitió el certificado para el sitio web al que me estaba conectando mediante el analizador COMODO SSL , descargué el certificado de esa autoridad e intenté agregar solo ese:

require('ssl-root-cas/latest')
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');

Terminé con otro error: CERT_UNTRUSTED. Finalmente, inyecté las CA raíz adicionales e incluí "mi" (aparentemente intermediario) CA, que funcionó:

require('ssl-root-cas/latest')
  .inject()
  .addFile(__dirname + '/comodohigh-assurancesecureserverca.crt');

1
Me estaba conectando a un sitio web con un certificado emitido por COMODO High-Assurance Secure Server CA. Descargué el certificado de su página de descargas .
Ferdinand Prantl

2
¡Gracias! Para mi problema, necesitaba agregar toda la cadena de certificados para superar este error. Para tener una referencia de otros, este post me mostró cómo exportar fácilmente los archivos necesarios pem a través de Firefox: superuser.com/a/97203
mfink

Bueno, gracias por la ayuda. En mi caso, al final fue una mala configuración del servidor SSL, no del nodo. No todos los certificados intermedios se instalaron en el servidor.
Scott Jungwirth

si obtiene el certificado como una .cerejecución esto openssl x509 -inform DER -in YOUR_CERTIFICATE.cer -out YOUR_CERTIFICATE.crtpara convertirlo de .crtantemano
0x1gene

8

Para la aplicación Create React (donde también se produce este error y esta pregunta es el resultado # 1 de Google), es probable que esté utilizando HTTPS=true npm starty un proxy(in package.json) que va a alguna API HTTPS que es autofirmado, cuando está en desarrollo.

Si ese es el caso, considere cambiar proxyasí:

"proxy": {
  "/api": {
    "target": "https://localhost:5001",
    "secure": false
  }
}

secure decide si el proxy de WebPack verifica o no la cadena de certificados y la desactivación asegura que el certificado autofirmado de la API no se verifique para que pueda obtener sus datos.


4

¡Puede ser muy tentador hacerlo rejectUnauthorized: falseo process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';no hacerlo! Te expone al hombre en los ataques medios.

Las otras respuestas son correctas porque el problema radica en el hecho de que su certificado está "firmado por una CA intermediaria". Hay una solución fácil para esto, una que no requiere una biblioteca de terceros como ssl-root-caso inyectar ninguna CA adicional en el nodo.

La mayoría de los clientes https en opciones de soporte de nodo que le permiten especificar una CA por solicitud, que se resolverá UNABLE_TO_VERIFY_LEAF_SIGNATURE. Aquí hay un ejemplo simple que usa el httpsmódulo incorporado del nodo .

import https from 'https';

const options = {
  host: '<your host>',
  defaultPort: 443,
  path: '<your path>',
  // assuming the bundle file is co-located with this file
  ca: readFileSync(__dirname + '/<your bundle file>.ca-bundle'),
  headers: {
    'content-type': 'application/json',
  }
};
https.get(options, res => {
  // do whatever you need to do
})

Sin embargo, si puede configurar los ajustes de SSL en su servidor de alojamiento, la mejor solución sería agregar los certificados intermedios a su proveedor de alojamiento. De esa forma, el solicitante del cliente no necesita especificar una CA, ya que está incluida en el servidor. Yo personalmente uso namecheap + heroku. El truco para mí fue crear un archivo .crt con cat yourcertificate.crt bundle.ca-bundle > server.crt. Luego abrí este archivo y agregué una nueva línea después del primer certificado. Puedes leer más en

https://www.namecheap.com/support/knowledgebase/article.aspx/10050/33/installing-an-ssl-certificate-on-heroku-ssl


Este error se presenta principalmente en el entorno local, no en la producción, por lo que si está en el sitio, está bien hacerlo: process.env ['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
Vivex

@Vivex: no está bien hacerlo en un entorno local si el objetivo es probar cómo funcionan sus certificados SSL y cómo se transmiten ...
dwanderson

2

Solo poner esto aquí en caso de que ayude a alguien, mi caso fue diferente y un poco extraño. Recibí esto en una solicitud a la que se accedió a través de superagent : el problema no tenía nada que ver con los certificados (que se configuraron correctamente) y todo que ver con el hecho de que luego estaba pasando el resultado de superagent a través de la devolución de llamada en cascada del módulo asíncrono . Para solucionarlo: en lugar de pasar el resultado completo, simplemente pase result.bodypor la devolución de llamada de la cascada.


2

Tuve los mismos problemas. He seguido la solución @ThomasReggi y @ CoolAJ86 y he trabajado bien, pero no estoy satisfecho con la solución.

Debido a que se produjo el problema "UNABLE_TO_VERIFY_LEAF_SIGNATURE" debido al nivel de configuración de la certificación.

Acepto la solución @thirdender, pero es una solución parcial. Según el sitio web oficial de nginx , mencionaron claramente que el certificado debe ser una combinación de El certificado del servidor y los certificados encadenados.

ingrese la descripción de la imagen aquí


1

También puede intentarlo poniendo estricto SSL a false, de esta manera:

{  
   url: "https://...",
   method: "POST",
   headers: {
        "Content-Type": "application/json"},
   strictSSL: false
}

0

Tuve un problema con mi configuración de Apache después de instalar un certificado GoDaddy en un subdominio. Originalmente pensé que podría ser un problema con Node no enviando un Indicador de nombre de servidor (SNI), pero ese no fue el caso. El análisis del certificado SSL del subdominio con https://www.ssllabs.com/ssltest/ devolvió el error Problemas de la cadena: Incompleto .

Después de agregar el gd_bundle-g2-g1.crtarchivo proporcionado por GoDaddy a través de la SSLCertificateChainFiledirectiva Apache, Node pudo conectarse a través de HTTPS y el error desapareció.


0

Debe incluir el certificado intermedio en su servidor. Esto resuelve el [Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE]


0

Otro enfoque para resolver esto de manera segura es usar el siguiente módulo.

node_extra_ca_certs_mozilla_bundle

Este módulo puede funcionar sin ninguna modificación de código al generar un archivo PEM que incluye todos los certificados raíz e intermedios confiables por Mozilla. Puede usar la siguiente variable de entorno (Funciona con Nodejs v7.3 +),

NODE_EXTRA_CA_CERTS

Para generar el archivo PEM para usar con la variable de entorno anterior. Puede instalar el módulo usando:

npm install --save node_extra_ca_certs_mozilla_bundle

y luego inicie su script de nodo con una variable de entorno.

NODE_EXTRA_CA_CERTS=node_modules/node_extra_ca_certs_mozilla_bundle/ca_bundle/ca_intermediate_root_bundle.pem node your_script.js

Otras formas de usar el archivo PEM generado están disponibles en:

https://github.com/arvind-agarwal/node_extra_ca_certs_mozilla_bundle

NOTA: Soy el autor del módulo anterior.


0

Si llega a este hilo porque está usando el módulo postgres / pg de nodo, hay una mejor solución que establecer NODE_TLS_REJECT_UNAUTHORIZEDo rejectUnauthorized, lo que conducirá a conexiones inseguras.

En su lugar, configure la opción "ssl" para que coincida con los parámetros de tls.connect :

{
  ca: fs.readFileSync('/path/to/server-ca.pem').toString(),
  cert: fs.readFileSync('/path/to/client-cert.pem').toString(),
  key: fs.readFileSync('/path/to/client-key.pem').toString(),
  servername: 'my-server-name' // e.g. my-project-id/my-sql-instance-id for Google SQL
}

He escrito un módulo de ayuda para analizar estas opciones de variables de entorno como PGSSLROOTCERT, PGSSLCERTy PGSSLKEY:

https://github.com/programmarchy/pg-ssl


0

Los siguientes comandos me funcionaron:

> npm config set strict-ssl false
> npm cache clean --force

El problema es que está intentando instalar un módulo desde un repositorio con un certificado SSL [Capa de sockets seguros] incorrecto o no confiable. Una vez que limpie el caché, este problema se resolverá. Es posible que tenga que convertirlo en verdadero más adelante.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.