Skip to content

Commit 471fe71

Browse files
joyeecheungRafaelGSS
authored andcommitted
cli: add NODE_USE_SYSTEM_CA=1
Similar to how NODE_USE_ENV_PROXY complements --use-env-proxy, this complements --use-system-ca. This will allow the setting to be applied to workers individually in the future. PR-URL: #59276 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ethan Arrowood <[email protected]> Reviewed-By: Darshan Sen <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]>
1 parent 64add63 commit 471fe71

File tree

5 files changed

+113
-0
lines changed

5 files changed

+113
-0
lines changed

‎doc/api/cli.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3649,6 +3649,18 @@ specified proxy.
36493649
This can also be enabled using the [`--use-env-proxy`][] command-line flag.
36503650
When both are set, `--use-env-proxy` takes precedence.
36513651

3652+
### `NODE_USE_SYSTEM_CA=1`
3653+
3654+
<!-- YAML
3655+
added: REPLACEME
3656+
-->
3657+
3658+
Node.js uses the trusted CA certificates present in the system store along with
3659+
the `--use-bundled-ca` option and the `NODE_EXTRA_CA_CERTS` environment variable.
3660+
3661+
This can also be enabled using the [`--use-system-ca`][] command-line flag.
3662+
When both are set, `--use-system-ca` takes precedence.
3663+
36523664
### `NODE_V8_COVERAGE=dir`
36533665

36543666
When set, Node.js will begin outputting [V8 JavaScript code coverage][] and
@@ -3977,6 +3989,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
39773989
[`--redirect-warnings`]: #--redirect-warningsfile
39783990
[`--require`]: #-r---require-module
39793991
[`--use-env-proxy`]: #--use-env-proxy
3992+
[`--use-system-ca`]: #--use-system-ca
39803993
[`AsyncLocalStorage`]: async_context.md#class-asynclocalstorage
39813994
[`Buffer`]: buffer.md#class-buffer
39823995
[`CRYPTO_secure_malloc_init`]: https://www.openssl.org/docs/man3.0/man3/CRYPTO_secure_malloc_init.html

‎doc/node.1‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,12 @@ This currently only affects requests sent over
841841
.Arfetch() .
842842
Support for other built-in http and https methods is under way.
843843
.
844+
.ItEvNODE_USE_SYSTEM_CA
845+
Similar to
846+
.Fl-use-system-ca .
847+
Use the trusted CA certificates present in the system store, in addition to the certificates in the
848+
bundled Mozilla CA store and certificates from `NODE_EXTRA_CA_CERTS`.
849+
.
844850
.ItEvNODE_V8_COVERAGEArdir
845851
When set, Node.js writes JavaScript code coverage information to
846852
.Ardir .

‎src/node.cc‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,15 @@ static ExitCode InitializeNodeWithArgsInternal(
868868
// default value.
869869
V8::SetFlagsFromString("--rehash-snapshot");
870870

871+
#if HAVE_OPENSSL
872+
// TODO(joyeecheung): make this a per-env option and move the normalization
873+
// into HandleEnvOptions.
874+
std::string use_system_ca;
875+
if (credentials::SafeGetenv("NODE_USE_SYSTEM_CA", &use_system_ca) &&
876+
use_system_ca == "1"){
877+
per_process::cli_options->use_system_ca = true;
878+
}
879+
#endif// HAVE_OPENSSL
871880
HandleEnvOptions(per_process::cli_options->per_isolate->per_env);
872881

873882
std::string node_options;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
// This tests that NODE_USE_SYSTEM_CA environment variable works the same
3+
// as --use-system-ca flag by comparing certificate counts.
4+
5+
constcommon=require('../common');
6+
if(!common.hasCrypto)common.skip('missing crypto');
7+
8+
consttls=require('tls');
9+
const{ spawnSyncAndExitWithoutError }=require('../common/child_process');
10+
11+
constsystemCerts=tls.getCACertificates('system');
12+
if(systemCerts.length===0){
13+
common.skip('no system certificates available');
14+
}
15+
16+
const{child: {stdout: expectedLength}}=spawnSyncAndExitWithoutError(process.execPath,[
17+
'--use-system-ca',
18+
'-p',
19+
`tls.getCACertificates('default').length`,
20+
],{
21+
env: { ...process.env,NODE_USE_SYSTEM_CA: '0'},
22+
});
23+
24+
spawnSyncAndExitWithoutError(process.execPath,[
25+
'-p',
26+
`assert.strictEqual(tls.getCACertificates('default').length, ${expectedLength.toString()})`,
27+
],{
28+
env: { ...process.env,NODE_USE_SYSTEM_CA: '1'},
29+
});
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Env: NODE_USE_SYSTEM_CA=1
2+
// Same as test-native-root-certs.mjs, just testing the environment variable instead of the flag.
3+
4+
import*ascommonfrom'../common/index.mjs';
5+
importassertfrom'node:assert/strict';
6+
importhttpsfrom'node:https';
7+
importfixturesfrom'../common/fixtures.js';
8+
import{it,beforeEach,afterEach,describe}from'node:test';
9+
import{once}from'events';
10+
11+
if(!common.hasCrypto){
12+
common.skip('requires crypto');
13+
}
14+
15+
// To run this test, the system needs to be configured to trust
16+
// the CA certificate first (which needs an interactive GUI approval, e.g. TouchID):
17+
// see the README.md in this folder for instructions on how to do this.
18+
consthandleRequest=(req,res)=>{
19+
constpath=req.url;
20+
switch(path){
21+
case'/hello-world':
22+
res.writeHead(200);
23+
res.end('hello world\n');
24+
break;
25+
default:
26+
assert(false,`Unexpected path: ${path}`);
27+
}
28+
};
29+
30+
describe('use-system-ca',function(){
31+
32+
asyncfunctionsetupServer(key,cert){
33+
consttheServer=https.createServer({
34+
key: fixtures.readKey(key),
35+
cert: fixtures.readKey(cert),
36+
},handleRequest);
37+
theServer.listen(0);
38+
awaitonce(theServer,'listening');
39+
40+
returntheServer;
41+
}
42+
43+
letserver;
44+
45+
beforeEach(asyncfunction(){
46+
server=awaitsetupServer('agent8-key.pem','agent8-cert.pem');
47+
});
48+
49+
it('trusts a valid root certificate',asyncfunction(){
50+
awaitfetch(`https://localhost:${server.address().port}/hello-world`);
51+
});
52+
53+
afterEach(asyncfunction(){
54+
server?.close();
55+
});
56+
});

0 commit comments

Comments
(0)