如何配置公理使用 SSL 证书?

我试图使用 axios 向 api 端点发出请求,但是得到了以下错误: Error: unable to verify the first certificate

Axios 使用的 https 模块似乎无法验证服务器上使用的 SSL 证书。

当用我的浏览器访问服务器时,证书是有效的,我可以看到/下载它。我还可以通过 https 向浏览器上的 API 发出请求。

我可以通过关闭验证来解决这个问题,这个代码有用。

const result = await axios.post(
`https://${url}/login`,
body,
{
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
}
)

问题是,这不会验证 SSL 证书,因此会打开安全漏洞。

如何配置公理系统以信任证书并正确验证它?

251393 次浏览

Create a custom agent with SSL certificate:

const httpsAgent = new https.Agent({
rejectUnauthorized: false, // (NOTE: this will disable client verification)
cert: fs.readFileSync("./usercert.pem"),
key: fs.readFileSync("./key.pem"),
passphrase: "YYY"
})


axios.get(url, { httpsAgent })


// or


const instance = axios.create({ httpsAgent })

From https://github.com/axios/axios/issues/284

Old question but chiming in for those who land here. No expert. Please consult with your local security gurus and what not.

Axios is an http(s) client and http clients usually participate in TLS anonymously. In other words, the server accepts their connection without identifying who is trying to connect. This is different then say, Mutual TLS where both the server and client verify each other before completing the handshake.

The internet is a scary place and we want to protect our clients from connecting to spoofed public endpoints. We do this by ensuring our clients identify the server before sending any private data.

// DO NOT DO THIS IF SHARING PRIVATE DATA WITH SERVICE
const httpsAgent = new https.Agent({ rejectUnauthorized: false });

This is often posted (and more egregiously upvoted) as the answer on StackOverflow regarding https client connection failures in any language. And what's worse is that it usually works, unblocks the dev and they move on their merry way. However, while they certainly get in the door, whose door is it? Since they opted out of verifying the server's identity, their poor client has no way of knowing if the connection they just made to the company's intranet has bad actors listening on the line.

If the service has a public SSL cert, the https.Agent usually does not need to be configured further because your operating system provides a common set of publicly trusted CA certs. This is usually the same set of CA certs your browser is configured to use and is why a default axios client can hit https://google.com with little fuss.

If the service has a private SSL cert (self signed for testing purposes or one signed by your company's private CA to protect their internal secrets), the https agent must be configured to trust the private CA used to sign the server cert:

const httpsAgent = new https.Agent({ ca: MY_CA_BUNDLE });

where MY_CA_BUNDLE is an array of CA certs with both the server cert for the endpoint you want to hit and that cert's complete cert chain in .pem format. You must include all certs in the chain up to the trust root.


Where are these options documented?

HTTPS is the HTTP protocol over TLS/SSL. In Node.js this is implemented as a separate module.

Therefore options passed to the https.Agent are a merge of the options passed to tls.connect() and tls.createSecureContext().

These configuration worked for me (In a Mutual Authentication scenario).

const httpsAgent = new https.Agent({
ca: fs.readFileSync("./resource/bundle.crt"),
cert: fs.readFileSync("./resrouce/thirdparty.crt"),
key: fs.readFileSync("./resource/key.pem"),
})

Note: bundle.crt was prepared from provided certificates (root,intermediate,end entry certificate). Unfortunately no clear documentation found in this regards.

For me, when my application is running in development mode, I have disabled rejectUnauthorized directly in axios.defaults.options. This works very well. be careful and use this only in developer mode.

import https from 'https'
import axios from 'axios'
import config from '~/config'


/**
* Axios default settings
*/
axios.defaults.baseURL = config.apiURL


/**
* Disable only in development mode
*/
if (process.env.NODE_ENV === 'development') {
const httpsAgent = new https.Agent({
rejectUnauthorized: false,
})
axios.defaults.httpsAgent = httpsAgent
// eslint-disable-next-line no-console
console.log(process.env.NODE_ENV, `RejectUnauthorized is disabled.`)
}

Good morning dear.

My problem is the following:

"Enable to verify the first certificate" with an error code 'ENABLE_TO_VERIFY_LEAF_SIGNATURE'.

They sent me a certificate with a .pfx extension and with the following commands I generated the .pem certificate and the key also with a .pem extension.

I attach the commands.

  • openssl pkcs12 -in certificate.pfx -nocerts -out key.pem -nodes
  • openssl pkcs12 -in certificate.pfx -nokeys -out certificate.pem

It should be noted that I am using axios to make the request.

I attach my agent configuration in axios.

const httpsAgent = new https.Agent ({
pfx: fs.readFileSync ("path.pfx"), passphrase: 'password', requestCert: true, rejectUnauthorized: true });

This what worked for me , using axios with nodejs + express

exports.test_ssl = async (req,res) => {
   

let cert_file = fs.readFileSync("./ssl/my_self_signed_certificate.crt")
let ca_file = fs.readFileSync("./ssl/my_self_signed_certificate_ca.crt")
const agent = new https.Agent({
requestCert: true,
rejectUnauthorized: true,
cert: cert_file,
ca: ca_file
});
const options = {
url: `https://51.195.45.154/test`,  // <---this is  a fake ip do not bother
method: "POST",
httpsAgent : agent,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/txt;charset=UTF-8'
},
data: {}
};




console.log(cert_file.toString())


axios(options)
.then(response => {
payload = response.data ;
return res.status(200).send({"status":1});
}).catch(err => {
console.log(err);
return false
});


}

This worked for me:

import axios from 'axios'
import https from 'https'


const headers = {};


const httpsAgent = new https.Agent({
ca: fs.readFileSync('./certs/cert.pem'),
cert: fs.readFileSync('./certs/cert.pem'),
})


const data = await axios.get(url, { httpsAgent, headers })


const https = require('https');
const axios = require('axios')


const CA = "-----BEGIN CERTIFICATE-----$$$$$-----END CERTIFICATE-----"
const url = "bla"
const httpsAgent = new https.Agent({
ca: CA
});


const response = await axios.get(url, { httpsAgent });

This is what work for me.

This is very dirty, but at the top of your script, just put:

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

This basically tells node to not check SSL certificates, which is very convenient when you get self signed certificates rejected in development.

Please don't use this in production.