Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
670b53b
tls: add 'as' option to getCACertificates() for X509Certificate output
haramj Aug 4, 2025
7a5dbcd
doc: fix getCACertificates() types and remove invalid escapes
haramj Aug 4, 2025
6fe1c7b
doc: fix undefined reference for X509Certificate and format markdown
haramj Aug 4, 2025
ac45e9d
Update doc/api/tls.md
haramj Aug 4, 2025
7c26f5e
Update doc/api/tls.md
haramj Aug 4, 2025
6db6b80
Update doc/api/tls.md
haramj Aug 4, 2025
5e55e1f
Update test/parallel/test-tls-get-ca-certificates-x509-option.js
haramj Aug 4, 2025
a9f099c
Update doc/api/tls.md
haramj Aug 4, 2025
150f805
tls: validate 'as' option using validateOneOf
haramj Aug 5, 2025
e69b7ed
test: expand getCACertificates() with 'as' option and invalid inputs
haramj Aug 5, 2025
2ac7e72
test: expand test-tls-get-ca-certificates-x509-option.js coverage
haramj Aug 5, 2025
c45c304
docs: add changes block for tls.getCACertificates ‘as’ option support
haramj Aug 5, 2025
d8a3138
doc: fix changes block
haramj Aug 5, 2025
135ba8a
tls: rename 'as' to 'format' in getCACertificates, default 'string'
haramj Aug 10, 2025
d9e8357
doc: format tls.md
haramj Aug 10, 2025
e3563a5
tls: simplify getCACertificates() API
haramj Aug 19, 2025
fbf223a
doc: fix broken anchor link for tls.getCACertificates()
haramj Aug 20, 2025
5129cb9
doc: update tls.md `X509Certificate` anchor
haramj Aug 31, 2025
24b8bc2
doc: fix tls.md lint error
haramj Aug 31, 2025
22ce735
doc: fix x509certificate anchor
haramj Aug 31, 2025
a6ebe6a
Update test/parallel/test-tls-get-ca-certificates-bundled.js
haramj Aug 31, 2025
a5aa848
doc: clarify format and return types in tls.getCACertificates()
haramj Aug 31, 2025
ba15d9f
test: fix tls.getCACertificates bundled test to use format 'string'
haramj Sep 1, 2025
c24e23e
test: keep shorthand arguments in getCACertificates tests
haramj Sep 2, 2025
1b254d2
test: Add final newline
haramj Sep 2, 2025
651a42d
tls: Improve getCACertificates() caching and test
haramj Sep 7, 2025
d4c3ac0
tls: Test rollback and Update getCACertificates()
haramj Sep 9, 2025
cea9639
doc: tls.md remove the white space
haramj Sep 10, 2025
e787797
tls: improve tls.getCACertificates() to simplify certificate handling
haramj Sep 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 26 additions & 11 deletions doc/api/tls.md
Original file line number Diff line number Diff line change
Expand Up @@ -2325,21 +2325,35 @@ const additionalCerts = ['-----BEGIN CERTIFICATE-----\n...'];
tls.setDefaultCACertificates([...currentCerts, ...additionalCerts]);
```

## `tls.getCACertificates([type])`
## `tls.getCACertificates([options])`

<!-- YAML
added:
- v23.10.0
- v22.15.0
-->

* `type` {string|undefined} The type of CA certificates that will be returned. Valid values
are `"default"`, `"system"`, `"bundled"` and `"extra"`.
**Default:** `"default"`.
* Returns: {string\[]} An array of PEM-encoded certificates. The array may contain duplicates
if the same certificate is repeatedly stored in multiple sources.

Returns an array containing the CA certificates from various sources, depending on `type`:
changes:
- version:
- REPLACEME
pr-url: https://github.com/nodejs/node/pull/59349
description: Added optional `options.type` parameter to `getCACertificates()`.
-->

* `options` {string|Object|undefined}
Optional. If a string, it is treated as the `type` of certificates to return.
If an object, it may contain:
* `type` {string} The type of CA certificates to return. One of `"default"`, `"system"`, `"bundled"`, or `"extra"`.
**Default:** `"default"`.
* `format` {string} The format of returned certificates. One of `"pem"`, `"der"`, or `"x509"`.
**Default:** `"pem"`.
* `"pem"` (alias: `"string"`): Returns an array of PEM-encoded certificate strings.
* `"der"` (alias: `"buffer"`): Returns an array of certificate data as `Buffer` objects in DER format.
* `"x509"`: Returns an array of [`X509Certificate`][x509certificate] instances.

* Returns: {Array}
An array of certificate data in the specified format:
* PEM strings when `format` is `"pem"` (or `"string"`).
* `Buffer` objects containing DER data when `format` is `"der"` (or `"buffer"`).
* [`X509Certificate`][x509certificate] instances when `format` is `"x509"`.

* `"default"`: return the CA certificates that will be used by the Node.js TLS clients by default.
* When [`--use-bundled-ca`][] is enabled (default), or [`--use-openssl-ca`][] is not enabled,
Expand Down Expand Up @@ -2513,7 +2527,7 @@ added: v0.11.3
[`tls.connect()`]: #tlsconnectoptions-callback
[`tls.createSecureContext()`]: #tlscreatesecurecontextoptions
[`tls.createServer()`]: #tlscreateserveroptions-secureconnectionlistener
[`tls.getCACertificates()`]: #tlsgetcacertificatestype
[`tls.getCACertificates()`]: #tlsgetcacertificatesoptions
[`tls.getCiphers()`]: #tlsgetciphers
[`tls.rootCertificates`]: #tlsrootcertificates
[`x509.checkHost()`]: crypto.md#x509checkhostname-options
Expand All @@ -2522,3 +2536,4 @@ added: v0.11.3
[cipher list format]: https://www.openssl.org/docs/man1.1.1/man1/ciphers.html#CIPHER-LIST-FORMAT
[forward secrecy]: https://en.wikipedia.org/wiki/Perfect_forward_secrecy
[perfect forward secrecy]: #perfect-forward-secrecy
[x509certificate]: crypto.md#class-x509certificate
47 changes: 44 additions & 3 deletions lib/tls.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ const { Buffer } = require('buffer');
const { canonicalizeIP } = internalBinding('cares_wrap');
const tlsCommon = require('internal/tls/common');
const tlsWrap = require('internal/tls/wrap');
const { validateString } = require('internal/validators');
const {
validateOneOf,
validateString,
} = require('internal/validators');
const { X509Certificate } = require('crypto');

const {
namespace: {
Expand Down Expand Up @@ -180,8 +184,7 @@ function cacheDefaultCACertificates() {
return defaultCACertificates;
}

// TODO(joyeecheung): support X509Certificate output?
function getCACertificates(type = 'default') {
function getCACertificatesAsStrings(type = 'default') {
validateString(type, 'type');

switch (type) {
Expand All @@ -197,6 +200,44 @@ function getCACertificates(type = 'default') {
throw new ERR_INVALID_ARG_VALUE('type', type);
}
}

function getCACertificates(options = undefined) {
if (typeof options === 'string' || options === undefined) {
return getCACertificatesAsStrings(options);
}

if (typeof options === 'object' && options !== null) {
const {
type = 'default',
format = 'pem',
} = options;

validateString(type, 'type');
validateOneOf(format, 'format', ['pem', 'der', 'x509', 'string', 'buffer']);

const certs = getCACertificatesAsStrings(type);

if (format === 'x509') {
return certs.map((cert) => new X509Certificate(cert));
}

if (format === 'pem' || format === 'string') {
return certs;
}

const buffers = certs.map((cert) => {
const base64 = cert.replace(/(?:\s|-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----)+/g, '');
return Buffer.from(base64, 'base64');
});

if (format === 'der' || format === 'buffer') {
return buffers;
}
}

throw new ERR_INVALID_ARG_TYPE('options', ['string', 'object'], options);
}

exports.getCACertificates = getCACertificates;

function setDefaultCACertificates(certs) {
Expand Down
3 changes: 0 additions & 3 deletions test/parallel/test-tls-get-ca-certificates-default.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,5 @@ const { assertIsCAArray } = require('../common/tls');
const certs = tls.getCACertificates();
assertIsCAArray(certs);

const certs2 = tls.getCACertificates('default');
assert.strictEqual(certs, certs2);

// It's cached on subsequent accesses.
assert.strictEqual(certs, tls.getCACertificates('default'));
66 changes: 66 additions & 0 deletions test/parallel/test-tls-get-ca-certificates-x509-option.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict';

const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const tls = require('tls');
const { X509Certificate } = require('crypto');

{
const certs = tls.getCACertificates({ type: 'default', format: 'x509' });
assert.ok(Array.isArray(certs));
assert.ok(certs.length > 0);
for (const cert of certs) {
assert.ok(cert instanceof X509Certificate);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use the helpers in test/common/tls.js to verify that they are serialized correctly (i.e. important properties are the same as before)? The same goes to the buffer results.

}
}

{
const certs = tls.getCACertificates({ type: 'default', format: 'buffer' });
assert.ok(Array.isArray(certs));
assert.ok(certs.length > 0);
for (const cert of certs) {
assert.ok(Buffer.isBuffer(cert));
}
}

{
const certs = tls.getCACertificates({ type: 'default' });
assert.ok(Array.isArray(certs));
assert.ok(certs.length > 0);
for (const cert of certs) {
assert.strictEqual(typeof cert, 'string');
assert.ok(cert.includes('-----BEGIN CERTIFICATE-----'));
}
}

{
assert.throws(() => {
tls.getCACertificates({ type: 'default', format: 'invalid' });
}, {
name: 'TypeError',
code: 'ERR_INVALID_ARG_VALUE',
message: /must be one of/
});
}

{
const certs = tls.getCACertificates({ format: 'buffer' });
assert.ok(Array.isArray(certs));
assert.ok(certs.length > 0);
for (const cert of certs) {
assert.ok(Buffer.isBuffer(cert));
}
}

{
assert.throws(() => {
tls.getCACertificates({ type: 'invalid', format: 'buffer' });
}, {
name: 'TypeError',
code: 'ERR_INVALID_ARG_VALUE',
message: "The argument 'type' is invalid. Received 'invalid'"
});
}
Loading