Skip to content

Commit 5af88e7

Browse files
committed
test: add macOS certificate filtering tests
1 parent fdb537e commit 5af88e7

File tree

6 files changed

+223
-0
lines changed

6 files changed

+223
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDSzCCAjOgAwIBAgIUJmC4/h9L3c8Arrxyo/+O73Owt9AwDQYJKoZIhvcNAQEL
3+
BQAwNTEhMB8GA1UEAwwYTm9kZUpTLVRlc3QtRXhwaXJlZC1Sb290MRAwDgYDVQQK
4+
DAdOb2RlLmpzMB4XDTIwMDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowNTEhMB8G
5+
A1UEAwwYTm9kZUpTLVRlc3QtRXhwaXJlZC1Sb290MRAwDgYDVQQKDAdOb2RlLmpz
6+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArkeWKdWP/YG89KiMCTYe
7+
9Q3DSMwzKeYrjtK5FeVxSHqo5za01VYCYsHpmTZFTM5P6nU6c889vZ0+C5lS1QAa
8+
JLgkUYpMMTk7ycAO0VKYugB9vHI3mQUH3Fkk7cilq5r1KyR1RqaGx7xhe49iFyXo
9+
zIE7C9fAQ4/DhqkuZlCnFg9PQLzKikgRdUUZsR/kvEAK30YyCcVs5po5oTGZB1VB
10+
gRoNYLPqSBCUtgfHEw2EIqRNQtgVwEuJVEclwbijkgIm4NFDCFKixbVE8KQFAuxr
11+
SFO8msDonubXJhCXZkNeh+diBMl7lglZEQU8o6ax0lqrV8mCPselXc0ipR/eD6aG
12+
XQIDAQABo1MwUTAdBgNVHQ4EFgQUN+lQVSG+5zPWNm/XiMcDMk9GVnowHwYDVR0j
13+
BBgwFoAUN+lQVSG+5zPWNm/XiMcDMk9GVnowDwYDVR0TAQH/BAUwAwEB/zANBgkq
14+
hkiG9w0BAQsFAAOCAQEASj1j/atg8qr3aZEsukmFaBf7eu4c0O0WwogTwCaSAEtn
15+
6et9G9rbg++X3JDHBv2PKiYdhSKTz2Kdsaau0fw0fmDkrFB5fwvzi6JU+LZ0Q8Ur
16+
jPlcks8sIdByX9mAbmf0Hur1qkPBoOm4BQNHrhEA+ExD8jbTAUukAOwH0mZV9ZzC
17+
B/7qVXwV6JmvdLXKDeinScnu1AIcYJVPUFEO2ZSkl+4XsdFogN+t4ryisosgFCtL
18+
AWkxA2/InBPBncDOUiceagJQdkGiyhsySxj/niLe8XUUo0p6/bYgqV7loJV6qkDA
19+
6KPH1RyigZMJ0SxNvj5oW1wcS3N2i/uX5csq9/w2nA==
20+
-----END CERTIFICATE-----
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCuR5Yp1Y/9gbz0
3+
qIwJNh71DcNIzDMp5iuO0rkV5XFIeqjnNrTVVgJiwemZNkVMzk/qdTpzzz29nT4L
4+
mVLVABokuCRRikwxOTvJwA7RUpi6AH28cjeZBQfcWSTtyKWrmvUrJHVGpobHvGF7
5+
j2IXJejMgTsL18BDj8OGqS5mUKcWD09AvMqKSBF1RRmxH+S8QArfRjIJxWzmmjmh
6+
MZkHVUGBGg1gs+pIEJS2B8cTDYQipE1C2BXAS4lURyXBuKOSAibg0UMIUqLFtUTw
7+
pAUC7GtIU7yawOie5tcmEJdmQ16H52IEyXuWCVkRBTyjprHSWqtXyYI+x6VdzSKl
8+
H94PpoZdAgMBAAECggEAAoFI6UUGktBAlQuvJ5q9iywteGhm+90xFxZ0TppDrJUG
9+
xHwG0WIxGpZK80bSbC4y+92/f1alPop6D9SeWi1sMsbqzrk8KyD1eQrnq56ST2oe
10+
ZI0Hu41U9ZfabgiKSRMrHvmhLejK2ygcBpijAk4rMHVTEfKB8vaoCtF3t0TFgg2k
11+
MkliPU9hCkrr17aYZSw8R2HiTM8hqixm7GrTihZzGFUa+N4NHZEbVkLQpCnifBly
12+
1ZyNL03FDSBClYRGvp2W6qO8uUi3cQuXyfXhoeHZx5AW+pVsmmZsxhNnyeJwCDcU
13+
+WgxU9uNeHWEYwVg3fTP3LLgRhnVBr3UuYI4GtWBiQKBgQDhRC9cTlOG9SrgHPZT
14+
reZNDQ9hhrcb1kbo1yJBIHFTihv0UIS6S36PmN+OgshbF5+G8Y8fvJJ8vuzMpDfC
15+
GNR53F6DHH/bngv3lgws/6F0X41TrzOA6+MkA4D6s5uGscSODCGuxkwjuZuKQzwo
16+
zAhx8t6RX/w1k4uXFPfYgX5vBwKBgQDGDppVCyRGpijdAdXVmmiQz/7q9M6YdFDX
17+
53pt8CIdCfYiT3+iOwPqHAddQdwVewC3WrEZ7S3PdxpKgDDpYkJ0+NtHhlYdGLR9
18+
Ti6Cvmfc+r8yYnmEAqIXAeac5A4MYYTh+FadgtzqVPhp8Q61xkXFwajo/tV1EcSt
19+
/A+rC0XiewKBgQCqniBZA6JUJ8FvucAApUg3t9qcfZKW7PcMSFXTiiULpyGBLLM6
20+
/w8+6AT7RadHB192r+M9oHA7N8jXPtJUmsXj/rs/Bwj4aH6b6fQS6RN6txyt85dI
21+
4GFL17OLLxpvLJm5FQs1+0+UB3L9h+s64z7KP6+/4DmAwt4JcoI+Y+ZFZQKBgHbE
22+
YwAEgmhrU63UX+qLgZD1aaRz0T/S4HfYM66hhZNsWdERYzRht2M4E6J00AmBjVhm
23+
ZjVp6UKz5WwvmyUY60lBwh0ODa29Ft7ddz6n95ioNOd97eifu5uYZDZI+7Oo9wqa
24+
5TXnN5q+AYlmKLAQid6g1y2BQ3fEg/DhanPjerDpAoGBAM7Sm4E4UMOCzHFCHehh
25+
bTzfz8oNGpkWI+5UctXZOkzQ3YVtTwB/+b5nuG7D5EI8mRGHmhXerkM2uAmShmWl
26+
a9Xyo9nswhDjanBcji+ZWIXFqOodclK4/3VE+VnbzlZMqpGnxUl88wWeBXEualZ0
27+
Z3lq9DNf/Fywlcl69thCNXQs
28+
-----END PRIVATE KEY-----
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDUTCCAjmgAwIBAgIUapTwHjAOdsC1qQUcKRKprxW7GvswDQYJKoZIhvcNAQEL
3+
BQAwNzEjMCEGA1UEAwwaTm9kZUpTLVRlc3QtTm8tUmVzdWx0LVJvb3QxEDAOBgNV
4+
BAoMB05vZGUuanMwIBcNMjYwNDA0MTgzMjUyWhgPMjEyNjAzMTExODMyNTJaMDcx
5+
IzAhBgNVBAMMGk5vZGVKUy1UZXN0LU5vLVJlc3VsdC1Sb290MRAwDgYDVQQKDAdO
6+
b2RlLmpzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomij2nGU2Lg0
7+
sD9OitlQlIAC6QEm3ziS8c3yX+wIhV/sZ/mRFt1cvFfIX7LFYl6zzDMI0Wgho422
8+
H9T4I5RRZ2Ms6IZ1e6+ERlqWDm3pS2nFglOR3AA1QUDt0pSfrtQjIc2yxeTMP7EO
9+
/LRZuGp1VOrR2kDP9JZC0+WLBBvtz/yFUICdrfDnm2d9b632Gl3CU/GiotMvt+oZ
10+
8J3WEh4y0vVdIwzMLV/jhoIgi0e9sZzSkB4ZmHCBOwl4asj8Yj8PS4q4AvXH2jms
11+
HmrsxUezsRrw9seccisexcC+akrJ4s1cqGXmi6MxqP3FO6yhSBdge6fMSNAETZ70
12+
qKL/Kk1t6QIDAQABo1MwUTAdBgNVHQ4EFgQULJNqn+YwH/flAsr8460+8ej1XQkw
13+
HwYDVR0jBBgwFoAULJNqn+YwH/flAsr8460+8ej1XQkwDwYDVR0TAQH/BAUwAwEB
14+
/zANBgkqhkiG9w0BAQsFAAOCAQEAMl8+Y1xRagBBKOluPcvTyV5BTleXLtF95wsj
15+
6SCTsSzmJiYQtBZA/pSoTS8+gEQb9hjN6dbYRDVY2pGyLrEVI/YE4zr4+Ug8vBXw
16+
UnZx4a76bUiT8iC7rBsqSeui7R56lbPQlxYjEKyX3oZgW9WzZ9NT3z9/u3mfTrW/
17+
TculuifSQHAi1X5r9IXFFABMyD8gDtQSfG+0e1E9KLyCMO3p8H/snz1hXIAUFnBD
18+
2b5QYiQRxUN2aO4PqJakxhDN844Vv6O+vQX618Fn+MqaL6qyPzJRo9qJe70/5xIu
19+
4Xs3ajp8Y3c5bb9vGtgLWsb3eUJ+AcZ2kttaBaIgiKqk4hTrDA==
20+
-----END CERTIFICATE-----
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCiaKPacZTYuDSw
3+
P06K2VCUgALpASbfOJLxzfJf7AiFX+xn+ZEW3Vy8V8hfssViXrPMMwjRaCGjjbYf
4+
1PgjlFFnYyzohnV7r4RGWpYObelLacWCU5HcADVBQO3SlJ+u1CMhzbLF5Mw/sQ78
5+
tFm4anVU6tHaQM/0lkLT5YsEG+3P/IVQgJ2t8OebZ31vrfYaXcJT8aKi0y+36hnw
6+
ndYSHjLS9V0jDMwtX+OGgiCLR72xnNKQHhmYcIE7CXhqyPxiPw9LirgC9cfaOawe
7+
auzFR7OxGvD2x5xyKx7FwL5qSsnizVyoZeaLozGo/cU7rKFIF2B7p8xI0ARNnvSo
8+
ov8qTW3pAgMBAAECggEAFFg1W7zqCh1GhGQ5y4zzhNa7BpiIAmMiN+Y2RtaDhBRY
9+
bKHyZJcwRxZcBG5EPvwMBo1yEla6uAlILO6kcu3hJf63dnK5hC1KzaFgC3NbS9Yh
10+
JsqfNUcAD3+PCy0RCnk1OXEnbut9ZpEghn7Kf8kzj4Km7RySBa/5CSBHwikEKQ85
11+
jO4dvtx0wDYbbvTrIcCKS74KoM10hioR3478m/6sx3sYau1bOUAUgvBBQc4WmdwJ
12+
Mxxz2ZqTQp4IyTGLIIS7vhyJLG9dcb1fapuMXjRYUn9i2ku9mbB+p/n514RLS+2W
13+
iS9IokYY2NwYv5Ue2cxvtmE5uVqx7Hkm4FEeFQJCHQKBgQDWLaT5mWRZaIMGyoas
14+
lmqqYM0gLlb9E9mxyPMc/BV9flV/8dTzSVarvGDJtefVQB4LHBOCXQYj9ZiqUsND
15+
5b7ZH/sVBNBfm/FR6rebKYXc0HOzhmCsoiuVSMRmpLZsWVpeX2BzCVJzES5ejm0o
16+
t3nGFzzLyOwWxrvp5zcGLwsNWwKBgQDCHyMHQ052QBujBs6PICd6pQ+VtcTSmXbX
17+
TUcUFptzdRRIZdnuM2r2ZhUcBV1RSrHFfpzeyMuTW1+sU4I+ggOeM15ui1XRJjHI
18+
FId6Ahj35QR/Jqrlyhde5g/xElY7/4Vlvw27DlrqrSa8QzsM32J8RoQB3SppuPlz
19+
lnZoB5uBCwKBgBuYbfUq6l8KtDcfyRJbnwqsxkErN1IMSLQ7a/eEE1DEAkgl5IYk
20+
IOKntuDGa0RyqmxMBcd6LNxdPHpVh4ssAtb+497la+OluAYR8+4t/21f/khXPAWC
21+
L5NgeM2w00BKkvYt28N2pATnZc4RE8d3PF1liRPIo4KbwIJ2pARL82SZAoGAW8cu
22+
33sx+HR83IoWVNLl93VctfJ3eP53knmF1niNzHuZOFV3QMhslMxUxKfAo/OFsxMW
23+
hbo3jZbQ1/+vf3Am17//sJIN49GEDc2u879UILfVdWxJtlTi0cpB1T9PKBS59A3t
24+
Jvg1geiVfMLog0CGJq2MMfln2Q5MWhrUJoEaQ1sCgYBGIrbT0Tpb/09w1qZ21kDk
25+
4iBAnKiy3KAeXlq3bVpfV+u/Ah6K7nvKIFtende/FoKFhiIu7YAFkOhIWRvBsRZ0
26+
KWt2rlHfjlk+iZN9NqaWQqfmUvemiuBxie7ddFmMJwK2YYmmSI1hnTQlVLHuqMs6
27+
fDfGqsm1Edj00rLA7f6ylg==
28+
-----END PRIVATE KEY-----

test/system-ca/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,34 @@ security add-certificates \
1818
security add-certificates \
1919
-k /Users/$USER/Library/Keychains/login.keychain-db \
2020
test/fixtures/keys/non-trusted-intermediate-ca.pem
21+
security add-trusted-cert \
22+
-k /Users/$USER/Library/Keychains/login.keychain-db \
23+
test/fixtures/keys/expired-root-cert.pem
24+
# Self-signed cert with trust settings that lack kSecTrustSettingsResult.
25+
security add-trusted-cert \
26+
-k /Users/$USER/Library/Keychains/login.keychain-db \
27+
test/fixtures/keys/selfsigned-no-result-root-cert.pem
28+
security trust-settings-export /tmp/node-trust-settings.plist
29+
CERT_SHA1=$(openssl x509 \
30+
-in test/fixtures/keys/selfsigned-no-result-root-cert.pem \
31+
-fingerprint -sha1 -noout | sed 's/.*=//;s/://g')
32+
/usr/libexec/PlistBuddy \
33+
-c "Delete :trustList:${CERT_SHA1}:trustSettings" \
34+
/tmp/node-trust-settings.plist
35+
/usr/libexec/PlistBuddy \
36+
-c "Add :trustList:${CERT_SHA1}:trustSettings array" \
37+
/tmp/node-trust-settings.plist
38+
/usr/libexec/PlistBuddy \
39+
-c "Add :trustList:${CERT_SHA1}:trustSettings:0 dict" \
40+
/tmp/node-trust-settings.plist
41+
security trust-settings-import /tmp/node-trust-settings.plist
42+
rm /tmp/node-trust-settings.plist
43+
# Duplicate cert in a second keychain
44+
security create-keychain -p "test" /tmp/node-test-dup.keychain
45+
security add-certificates \
46+
-k /tmp/node-test-dup.keychain \
47+
test/fixtures/keys/fake-startcom-root-cert.pem
48+
security list-keychains -d user -s login.keychain-db /tmp/node-test-dup.keychain
2149
```
2250

2351
**Removing the certificate**
@@ -29,6 +57,12 @@ security delete-certificate -c 'NodeJS-Test-Intermediate-CA' \
2957
-t /Users/$USER/Library/Keychains/login.keychain-db
3058
security delete-certificate -c 'NodeJS-Non-Trusted-Test-Intermediate-CA' \
3159
-t /Users/$USER/Library/Keychains/login.keychain-db
60+
security delete-certificate -c 'NodeJS-Test-Expired-Root' \
61+
-t /Users/$USER/Library/Keychains/login.keychain-db
62+
security delete-certificate -c 'NodeJS-Test-No-Result-Root' \
63+
-t /Users/$USER/Library/Keychains/login.keychain-db
64+
security list-keychains -d user -s login.keychain-db
65+
security delete-keychain /tmp/node-test-dup.keychain
3266
```
3367

3468
## Windows
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Flags: --use-system-ca
2+
3+
import * as common from '../common/index.mjs';
4+
import assert from 'node:assert/strict';
5+
import * as fixtures from '../common/fixtures.mjs';
6+
import { it, describe } from 'node:test';
7+
import { includesCert, extractMetadata } from '../common/tls.js';
8+
import { execFileSync } from 'node:child_process';
9+
10+
if (!common.hasCrypto) {
11+
common.skip('requires crypto');
12+
}
13+
14+
if (process.platform !== 'darwin') {
15+
common.skip('macOS-specific test');
16+
}
17+
18+
function isCertInKeychain(cn) {
19+
try {
20+
execFileSync('security', ['find-certificate', '-c', cn], { stdio: 'pipe' });
21+
return true;
22+
} catch {
23+
return false;
24+
}
25+
}
26+
27+
function isDupKeychainPresent() {
28+
try {
29+
const out = execFileSync(
30+
'security', ['list-keychains', '-d', 'user'],
31+
{ encoding: 'utf8' },
32+
);
33+
return out.includes('node-test-dup.keychain');
34+
} catch {
35+
return false;
36+
}
37+
}
38+
39+
const { default: tls } = await import('node:tls');
40+
41+
const systemCerts = tls.getCACertificates('system');
42+
const fakeStartcomCert = fixtures.readKey('fake-startcom-root-cert.pem');
43+
if (!includesCert(systemCerts, fakeStartcomCert)) {
44+
common.skip(
45+
'fake-startcom-root-cert.pem not found in system CA store. ' +
46+
'Please follow setup instructions in test/system-ca/README.md',
47+
);
48+
}
49+
if (!isDupKeychainPresent()) {
50+
common.skip(
51+
'Duplicate keychain not set up. ' +
52+
'Please follow setup instructions in test/system-ca/README.md',
53+
);
54+
}
55+
if (!isCertInKeychain('NodeJS-Test-Expired-Root')) {
56+
common.skip(
57+
'Expired cert not installed. ' +
58+
'Please follow setup instructions in test/system-ca/README.md',
59+
);
60+
}
61+
62+
describe('macOS certificate filtering', () => {
63+
it('includes self-signed cert with absent kSecTrustSettingsResult', () => {
64+
const noResultCert = fixtures.readKey('selfsigned-no-result-root-cert.pem');
65+
assert.ok(
66+
includesCert(systemCerts, noResultCert),
67+
'Self-signed cert with absent kSecTrustSettingsResult ' +
68+
'(defaulting to TrustRoot) should be in system CA list',
69+
);
70+
});
71+
72+
it('deduplicates certificates from multiple keychains', () => {
73+
const target = extractMetadata(fakeStartcomCert);
74+
const matches = systemCerts.filter((c) => {
75+
const m = extractMetadata(c);
76+
return m.serialNumber === target.serialNumber &&
77+
m.issuer === target.issuer &&
78+
m.subject === target.subject;
79+
});
80+
assert.strictEqual(
81+
matches.length, 1,
82+
`Expected exactly 1 copy of fake-startcom-root-cert, found ${matches.length}`,
83+
);
84+
});
85+
86+
it('filters out expired certificates', () => {
87+
const expiredCert = fixtures.readKey('expired-root-cert.pem');
88+
assert.ok(
89+
!includesCert(systemCerts, expiredCert),
90+
'Expired certificate should not be in system CA list',
91+
);
92+
});
93+
});

0 commit comments

Comments
 (0)