crypto: add support for intermediate certs in --use-system-ca

PR-URL: https://github.com/nodejs/node/pull/57164
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
Tim Jacomb 2025-03-05 15:27:26 +00:00 committed by GitHub
parent 4e222aea82
commit b4c8440109
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 573 additions and 81 deletions

View File

@ -630,6 +630,21 @@ void ReadWindowsCertificates(
CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY,
L"ROOT");
// Grab the intermediate certs
GatherCertsForLocation(
system_root_certificates_X509, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"CA");
GatherCertsForLocation(system_root_certificates_X509,
CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY,
L"CA");
GatherCertsForLocation(system_root_certificates_X509,
CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
L"CA");
GatherCertsForLocation(
system_root_certificates_X509, CERT_SYSTEM_STORE_CURRENT_USER, L"CA");
GatherCertsForLocation(system_root_certificates_X509,
CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY,
L"CA");
// Grab the user-added trusted server certs. Trusted end-entity certs are
// only allowed for server auth in the "local machine" store, but not in the
// "current user" store.

View File

@ -40,6 +40,14 @@ all: \
ec-cert.pem \
ec.pfx \
fake-cnnic-root-cert.pem \
intermediate-ca-cert.pem \
intermediate-ca-key.pem \
leaf-from-intermediate-cert.pem \
leaf-from-intermediate-key.pem \
non-trusted-intermediate-ca-cert.pem \
non-trusted-intermediate-ca-key.pem \
non-trusted-leaf-from-intermediate-cert.pem \
non-trusted-leaf-from-intermediate-key.pem \
rsa_private.pem \
rsa_private_encrypted.pem \
rsa_private_pkcs8.pem \
@ -236,6 +244,102 @@ fake-startcom-root-cert.pem: fake-startcom-root.cnf \
echo '01' > fake-startcom-root-serial
touch fake-startcom-root-database.txt
intermediate-ca-key.pem:
openssl genrsa -out intermediate.key 2048
intermediate-ca-cert.pem: intermediate-ca-key.pem
openssl req -new \
-sha256 \
-nodes \
-key intermediate.key \
-subj "/C=US/ST=CA/L=SF/O=NODEJS/CN=NodeJS-Test-Intermediate-CA" \
-out test-intermediate-ca.csr
openssl x509 -req \
-extensions v3_ca \
-extfile fake-startcom-root.cnf \
-in test-intermediate-ca.csr \
-CA fake-startcom-root-cert.pem \
-CAkey fake-startcom-root-key.pem \
-CAcreateserial \
-out intermediate-ca.pem \
-days 99999 \
-sha256
rm -f test-intermediate-ca.csr
leaf-from-intermediate-key.pem:
openssl genrsa -out leaf-from-intermediate-key.pem 2048
leaf-from-intermediate-cert.pem: leaf-from-intermediate-key.pem
openssl genrsa -out leaf-from-intermediate-key.pem 2048
openssl req -new \
-sha256 \
-nodes \
-key leaf-from-intermediate-key.pem \
-addext "subjectAltName = DNS:localhost" \
-subj "/C=US/ST=CA/L=SF/O=NODEJS/CN=localhost" \
-out leaf-from-intermediate-cert.csr
openssl x509 -req \
-in leaf-from-intermediate-cert.csr \
-CA intermediate-ca.pem \
-CAkey intermediate.key \
-CAcreateserial \
-out leaf-from-intermediate-cert.pem \
-days 99999 \
-copy_extensions copy \
-sha256
rm -f leaf-from-intermediate-cert.csr
non-trusted-intermediate-ca-key.pem:
openssl genrsa -out non-trusted-intermediate.key 2048
non-trusted-intermediate-ca-cert.pem: non-trusted-intermediate-ca-key.pem
openssl req -new \
-sha256 \
-nodes \
-key non-trusted-intermediate.key \
-subj "/C=US/ST=CA/L=SF/O=NODEJS/CN=NodeJS-Non-Trusted-Test-Intermediate-CA" \
-out non-trusted-test-intermediate-ca.csr
openssl x509 -req \
-extensions v3_ca \
-extfile fake-startcom-root.cnf \
-in non-trusted-test-intermediate-ca.csr \
-passin "pass:password" \
-CA ca1-cert.pem \
-CAkey ca1-key.pem \
-CAcreateserial \
-out non-trusted-intermediate-ca.pem \
-days 99999 \
-sha256
rm -f non-trusted-test-intermediate-ca.csr
non-trusted-leaf-from-intermediate-key.pem:
openssl genrsa -out non-trusted-leaf-from-intermediate-key.pem 2048
non-trusted-leaf-from-intermediate-cert.pem: non-trusted-leaf-from-intermediate-key.pem
openssl genrsa -out non-trusted-leaf-from-intermediate-key.pem 2048
openssl req -new \
-sha256 \
-nodes \
-key non-trusted-leaf-from-intermediate-key.pem \
-addext "subjectAltName = DNS:localhost" \
-subj "/C=US/ST=CA/L=SF/O=NODEJS/CN=localhost" \
-out non-trusted-leaf-from-intermediate-cert.csr
openssl x509 -req \
-in non-trusted-leaf-from-intermediate-cert.csr \
-CA non-trusted-intermediate-ca.pem \
-CAkey non-trusted-intermediate.key \
-CAcreateserial \
-out non-trusted-leaf-from-intermediate-cert.pem \
-days 99999 \
-copy_extensions copy \
-sha256
rm -f non-trusted-leaf-from-intermediate-cert.csr
#
# agent1 is signed by ca1.
#

View File

@ -1 +1 @@
147D36C1C2F74206DE9FAB5F2226D78ADB00A426
147D36C1C2F74206DE9FAB5F2226D78ADB00A428

25
test/fixtures/keys/intermediate-ca.pem vendored Normal file
View File

@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIEOTCCAyGgAwIBAgIULe6EHUBNm9nZz+fYRZx1P8uqmGwwDQYJKoZIhvcNAQEL
BQAwfTELMAkGA1UEBhMCSUwxFjAUBgNVBAoMDVN0YXJ0Q29tIEx0ZC4xKzApBgNV
BAsMIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxKTAnBgNVBAMM
IFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MCAXDTI1MDIyMTIyMTYx
N1oYDzIyOTgxMjA2MjIxNjE3WjBeMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0Ex
CzAJBgNVBAcMAlNGMQ8wDQYDVQQKDAZOT0RFSlMxJDAiBgNVBAMMG05vZGVKUy1U
ZXN0LUludGVybWVkaWF0ZS1DQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAKfGhM1vXISvBuEJv4yapacu1CFnH9hQ6Z7e8p1kjMjaSg+NSvofPeb6byel
Jk7GI9wRN4ZQISpKNxvQAjyc9RqkAwUDPY9KEp38PSQFU4osqvJDP4zf2dn0Hl55
4DW22JzaWdwGgvq0admVwUBMnly4fVGBuxvy1m/j5wM6DHoSbC0Kgs13P2TpaqRT
jz7jzN5YaT16M3kTDKVcTQGzZOCro0JF+V4xIDiOV9v9Cy4F6FRuksHx/e7gWXSF
qaHqzblr9k/c8/3md5aBwHeUGJHe1+U/hhfE4D8IgG3ZdwNFI9KH5Zc8KfGTgr6s
fgbpnNg7p9d5VJNOOM4So8ybig8CAwEAAaOBzTCByjAMBgNVHRMEBTADAQH/MB0G
A1UdDgQWBBR6olPWoViHQBOxuAyYPRUSGaoEYDCBmgYDVR0jBIGSMIGPoYGBpH8w
fTELMAkGA1UEBhMCSUwxFjAUBgNVBAoMDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsM
IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxKTAnBgNVBAMMIFN0
YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggkAgg9vTE81yAowDQYJKoZI
hvcNAQELBQADggEBAC7nBG4JxrSFT/mJlCJxeHfFQj3xqduYePWK5H/h+buuX6OW
pjMA8se2SjQUfVn81GAtNxb1kX8o9HjmaTvkx8bq6iuF9oyJh96N22Hl3kfWXX6H
jy74Ur/pq73gpC90Xx8/DALpAYr9vKOKJM7DHWW9iuksRRvM1yh8kZagO0ewI8xU
I9DLzl6+Zu6ZChosMlIn7yGdXB3Wi5mO+1fN+ryFlOVfTurzeinDbLm4xHb6pLnP
x3VL1kKzQurUcvQvaIT3x3vd/FP+O7B+pWNyUE7HXZ9J4E2maUC+q81cpgAiCFoN
ks7RFmz1z2myhB8opEpgRFYu6lxjCtHsr+meLjo=
-----END CERTIFICATE-----

28
test/fixtures/keys/intermediate.key vendored Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCnxoTNb1yErwbh
Cb+MmqWnLtQhZx/YUOme3vKdZIzI2koPjUr6Hz3m+m8npSZOxiPcETeGUCEqSjcb
0AI8nPUapAMFAz2PShKd/D0kBVOKLKryQz+M39nZ9B5eeeA1ttic2lncBoL6tGnZ
lcFATJ5cuH1Rgbsb8tZv4+cDOgx6EmwtCoLNdz9k6WqkU48+48zeWGk9ejN5Ewyl
XE0Bs2Tgq6NCRfleMSA4jlfb/QsuBehUbpLB8f3u4Fl0hamh6s25a/ZP3PP95neW
gcB3lBiR3tflP4YXxOA/CIBt2XcDRSPSh+WXPCnxk4K+rH4G6ZzYO6fXeVSTTjjO
EqPMm4oPAgMBAAECggEAAMP0GSfX6TcPNfmgaRjPhqq9BwX8bDU6S6JCwxsRVV1B
lz6Sx/9affJIjYrAWP2objmZ4j/9Vr8N70+MoxAoQh3bcatpHX0+BoB/Gun3TpsT
kJVj9dWTnd3yQYYW0sfpxxVr8YgKEvC9xuNbBVsUIeIpmDSaUO9TsSD+DdK2+duX
wKPjCe097669ZG994GP9ilG6FdfIlVNWHWPExmFgbx0ydXr97nDuurt72HnqCVRR
95g9SNAbkadUVj7iTSVovuaIQpQY4BMFICsGGRo10mMFGTzpAUwsl6OVZTUZXaST
dg/Wl8ZD98CucVFmk546pJrfPDvk+qLqt0hlkXA5mQKBgQDrqPCNzz/VhsIlTmuO
Dgmf4q9/hglR8JKjMQTuEXLGAhA09ZZrhKsGYSkciXEzmlL5mGZX+83Ss+ns8nI7
21e6ZYm5hokltVbZ2Of2xGyeZ0SZ22QwIm4Eg2MmEpmyXAMTKAfvuvfQW1dC0UXG
JEiRBYq3Chxv82ExmlkU5gZNIwKBgQC2QaCnPVV/VkwF0912lto8IRpwgZ0Jrj4b
xqKTCc7oFNzd4Ua/I0W9qPqR1ORyVpq0li7cjHDmFWCZZMbCgy7+g5eclaZ3qWZZ
Faj4rpv7y7ODKz2W2cmug9fWrrtsr96ohW1rfVn5racbHKAsT4f+RB+Gi1NK6aWp
tOmh4MRMJQKBgQDLSk5RluJTOc/LTO39emCVG4EXejIaDHUC8Ct3j3e6FleSx/S9
xZGfjDth0bLkuBEyHWTUK3UveWKns7IVrq7sLeF0OPmgnOFSRgo81s94ik8khpzT
5S+RFyJ12n/Z3AQPB25pQJm8lL8e9dbCCdTLvcMfCUrkzEgg+Sw1mgT/jwKBgQCM
7xbB/CW/AAZtgzV/3IsJcDe3xCKhN8IDTIiu1yjOQkPAt9EzQJ1PWfnZBx1YZSvg
dTnrhhZPdTxroYgpJbQTT8LPbNF7Ot1QCfXNx4gLH6vCxI8ttV/FuWIQOrHoC99L
xVGlixsmfWf5CRu66A0rS5ZtPhO8nAxkvOblLJ/emQKBgQCQkhBrZTDwgD4W6yxe
juo/H/y6PMD4vp68zk/GmuV7mzHpYg18+gGAI57dQoxWjjMxxhkB8WKpnEkXXiva
5YHq4ARUhXnPuNckvnOBj9jjy8HMeDKTPfZ6frv+B9i1y0N3ArerhPx44zCFpllH
BlVhzBa52wYAtbjg291+/G1ndw==
-----END PRIVATE KEY-----

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDkjCCAnqgAwIBAgIUPgpDrWcCOmjk4xOAkLpxa7UTx/4wDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G
A1UECgwGTk9ERUpTMSQwIgYDVQQDDBtOb2RlSlMtVGVzdC1JbnRlcm1lZGlhdGUt
Q0EwIBcNMjUwMjIxMjIxNjUyWhgPMjI5ODEyMDYyMjE2NTJaMEwxCzAJBgNVBAYT
AlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoMBk5PREVKUzES
MBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAnnWYLNbVnE2veKzF28rarJh0En4Rd5+1ZwHp7+iP2gjEVmjBaSGK/F80MV9l
S/wtZskUoZH0aKwiq9ly6Jp9IETte9Tk1Td6jTUeG8Vs9N6zoZcXM2Q359xbA+0X
YzvHwD6TM5LQ6l3RKhJT2BRNz0oOCVQGHGepbcLbX99E3yXW0yXvZKAIcZY0NEk2
AZ1eDz7QAhdPQ6W8QuYjlqOa+wmxqzVb3RReMg3zrL9jfd4AgCT9IN7HMB0FkQys
y78EUHa12wlJkzHzz9N8+Qjt0537LjDpBuUBgnPn7Ukvz1kzD6q8a/dbB2RIbfVK
7o0I/P9hJuXPhRpZQeDRQmDt+QIDAQABo1gwVjAUBgNVHREEDTALgglsb2NhbGhv
c3QwHQYDVR0OBBYEFJHfQLpEP+M7+PYoxk/bY1vuDv/4MB8GA1UdIwQYMBaAFHqi
U9ahWIdAE7G4DJg9FRIZqgRgMA0GCSqGSIb3DQEBCwUAA4IBAQCXckUku5JZiXSb
qvlFH1JS7/SVeugquYZyI+boIzS2ykrLBkCVCbg6dD75Nu5VlcEGq4UNlY7vdfhk
wG/jHNe6Hm36Lm2vbwH3z21IIGZlkw4cbNzdeT5WQuQNoembtbaZSsE7s1Hs052l
kVJnq0ZJ7YgO54/0C9mE7dqhWHHWm9wPUC4emucqCKYcu1M9/onZgjjmAh39G473
1qlWuTacywQHHCg8B0w+iZlV1rJ93dTyxJvg+fgmQj2FqBNqOXu6ojhOWHt62D3Y
55zXFoUqToY6kgF+e9Rkn2vbZsSQO+cXSKVyRjnfIOCC4zO37yl31q02ouVv1Uct
ubqxlcPA
-----END CERTIFICATE-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCedZgs1tWcTa94
rMXbytqsmHQSfhF3n7VnAenv6I/aCMRWaMFpIYr8XzQxX2VL/C1myRShkfRorCKr
2XLomn0gRO171OTVN3qNNR4bxWz03rOhlxczZDfn3FsD7RdjO8fAPpMzktDqXdEq
ElPYFE3PSg4JVAYcZ6ltwttf30TfJdbTJe9koAhxljQ0STYBnV4PPtACF09DpbxC
5iOWo5r7CbGrNVvdFF4yDfOsv2N93gCAJP0g3scwHQWRDKzLvwRQdrXbCUmTMfPP
03z5CO3TnfsuMOkG5QGCc+ftSS/PWTMPqrxr91sHZEht9UrujQj8/2Em5c+FGllB
4NFCYO35AgMBAAECggEACIfP4A0WPZaEjWhus+cLJ+rCp+qzxcb6KPAWUBkq4lvh
tv2neOGKhgzZhlVqgoFST+PgGZUeDWMD8FCx4hIMDahMSSP0SEK29SJgizHxDEsv
bDHyOKzq4g9vsmnJfij+F0w/GDINj2pqy9sl+p5YNII5+HhWpmGRwlQQw4vlXSZq
hcubO1DyL/3FL0gVMHUZex86QJ9cYXkf++omaFNPaOsiKbZu7Whtg4rxJOBw38FD
/fX4U6SQwSxI6ffxFbmGvSBAQW4333Qvbs0xZnusKrcaKNQ3kCoQ7+cgyDogwSAE
TQN1mqPynGlMmTW4KyyR1/W0jpQEW+pll2DNCqHb8QKBgQDONX8QXu2mp/5qjXJK
Sa1orgqneadbWiUfq+6vWEIwAWbcUYGqgzUNa9OeK8jV5hEsCJOrfPvhKYdyVrfr
cu8mLtQFQLZzTlaEyX4a8Euk2xlHIYG7/giEnBugdHcHu9MV7TLRFzunc5Y4cA4W
3crScf/gl+LDO3TZ5E3ZHu4u8QKBgQDEuIagHlhcuyEfHUPRJk6ZXexlkQ383f3/
g1aqWQxxPnlZuo/wFyxVl7YP5VNELOsiCQHm2efk+8dx0Fc8jzuafp8iSnSOJnNM
7C9K5JcbkxsJxArx1Z2ZMPfFM40Nw5kFYNCPhsuzZ/w+/eOe2EyFEZMkWdH5lMpw
Y6GvxiS/iQKBgB6WLs/F1OhoeMNjUbWVMiSZ1Di9Qca6G1GUViYqKD8ophI+AMbD
CYaBHPWUNwkLRDbM2uKP+miOmWmrVUKWXMTEI2zYCXgXAZxWqt7iD8ZXPWugm7a/
2pGY+jwVqmY6RPg2o9gB4zZWXcznSh+4LFKE2Fh/DwK4ef+r7qQrA1dxAoGAdIEI
EfoGwNx+cCvnxw0VzZSndTtj+lcKn3GMORTF3qduPOrVZg6DTimsRFu/ZYfotV56
RtrUkHNgmhIWKCJ33TaSTj+kKa+x52OVWphouYb0o2L8TF8Dl/89LggqyHUHwfyl
Z+sf5p9172RzktZs8v4Gk6eySEqLXeZTkoMZrmkCgYEAg8QV0rE1GprYoL02DiMT
/KlRyOUGawz559Rr5Ufdrm/SA37Yhyp/eADq1jrkpoL0uBd4YsqOFAtkCofxnI9i
BonK/T1JV1+wDnXYCU9Tis/d043/vCR4RVXQGfucmrPxjuObXCu5c8Q0DzpzLG3u
HmotaQ9Z3Wdd9PaX4le87R8=
-----END PRIVATE KEY-----

View File

@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIESTCCAzGgAwIBAgIUFH02wcL3Qgben6tfIibXitsApCgwDQYJKoZIhvcNAQEL
BQAwejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G
A1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTExIDAe
BgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMCAXDTI1MDIyNzA4MTczM1oY
DzIyOTgxMjEyMDgxNzMzWjBqMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJ
BgNVBAcMAlNGMQ8wDQYDVQQKDAZOT0RFSlMxMDAuBgNVBAMMJ05vZGVKUy1Ob24t
VHJ1c3RlZC1UZXN0LUludGVybWVkaWF0ZS1DQTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMH8MfKXtkBMn58gJVCwe2w/XOl9rNK0M348KFcYTStC2ta0
pwaB4ax7NeXs/xCDqtbuweZ0SLcS/nAOP9KQHN+fNSiXQ0gnHh23rZRri9VCvLWE
5mGle2yjBApz7JERLW7gZX1Xtw/X5Qt9CtIYVKf7rGTgkq0kSvJQf6DhJ8e68HwG
EQCp8ZmPQTFhIgzB35wYTgeKTU3uvQAYsAIw9fC5Vta8U9uU0VyN7mFxsoMXm4/u
prk9L4AYSOFIV+njTd8xL+puSfZSKQA8yLcZ1LeRkAZo3RjUcEUPRDdLxB1UAZvh
LYcJggWmx7799MZOsF1u9d2wR9HJ1Nzg3+IJiW0CAwEAAaOB1DCB0TAMBgNVHRME
BTADAQH/MB0GA1UdDgQWBBR9aYwxOpYpUe2jMoN0MAqeG4A8GzCBoQYDVR0jBIGZ
MIGWoX6kfDB6MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNG
MQ8wDQYDVQQKDAZKb3llbnQxEDAOBgNVBAsMB05vZGUuanMxDDAKBgNVBAMMA2Nh
MTEgMB4GCSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmeCFEqxbI39an0NLfyr
35xLDpLGrQIpMA0GCSqGSIb3DQEBCwUAA4IBAQDADBpifaPV4jRtSefetMnhxxwj
tPlLXRWqEJpJy+nHYJJdwQHxFHVoZSPinGpYpECCV73Gkh/rMKa+cvR4dBBIK6DP
Bl1IQNP4Jr90z9c0T/zzUxVXE4iwcv2/Vg5OvVHU3z5gW4Mk3R4Rb+69UWHB1z8D
41sm9w4u30vKGJrkdQ5ZLtfRLonncwLQexTlj1k/8VRytP4S9uIAmXwQpEPZxsto
pRcMO2aWW0PvDzk7WPU+ZKnf1RC+pQx+PPH1/ZfyXHy7njJKZ04plIdTA/ah9pPw
Bl++VCO7LSwDz+FlmuHnxc2LMR2EIRiNV03ooSc5XGGhIOKLl6+nMPQ0dlta
-----END CERTIFICATE-----

View File

@ -0,0 +1 @@
78A88418149F0BFCEC38DC14D085BA43D36090F0

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDB/DHyl7ZATJ+f
ICVQsHtsP1zpfazStDN+PChXGE0rQtrWtKcGgeGsezXl7P8Qg6rW7sHmdEi3Ev5w
Dj/SkBzfnzUol0NIJx4dt62Ua4vVQry1hOZhpXtsowQKc+yRES1u4GV9V7cP1+UL
fQrSGFSn+6xk4JKtJEryUH+g4SfHuvB8BhEAqfGZj0ExYSIMwd+cGE4Hik1N7r0A
GLACMPXwuVbWvFPblNFcje5hcbKDF5uP7qa5PS+AGEjhSFfp403fMS/qbkn2UikA
PMi3GdS3kZAGaN0Y1HBFD0Q3S8QdVAGb4S2HCYIFpse+/fTGTrBdbvXdsEfRydTc
4N/iCYltAgMBAAECggEALR4V1OVd1Xss1gMRQsDlV/Itzz20dEZGwrnFrSohCqqQ
QQc/4MbVIPuAN/PFCEeDdN2PuiS6I+B2TsQ1qmjr2kQKhmAWHUJB4ioOJHrWCVou
D27zcWsed5A7uJ2pPD1ZSpRE7p/32ya85kzlNyPDDtX9jPHhk4UhLFY2NQohKTYF
CM2+YL6V8x2Kq9OOjGxPrX3t5H0cgVW7f+mMwhCSevJQAoLWO7cNbbN/fWHEK0jn
ovHkpmK7dWejWN8MYMQOhmIuUV54aLIKoNLEAhnFj70/36I/GMUSQf+rCjjQtLXb
lmNiKF33+3L6ti9HdcznhJujtMjiAXloRkESKcYPoQKBgQDoKO9wj7ZUvapt7ZnD
9ALwkVpxPPCA7rDdu9DmEmXt8Zf3pVCaw1K2qPWM1iAoL6/AZDPs2E1nJGsmDNYv
wMPt09TsZTURKvQYfdFs0uZPcTCJAXg36+dgxXq1OUNirB7Z+F1QPE3EHZT5AaPc
vxRfA4RyJ+DcfMFzUcjePd2MTQKBgQDV57bQKf5wHkWCLVl/ZJB+hy1futN9In6u
n0UeqSK+8m7Go8rPvNFlTeY6/lz/bm58u0mJFKd7vNQs+l7Y1DitC7BLItNwtcuW
OEnhltbhry6i/9lieF607kwq9sNTVpp+iROF1BRmeDh3d3ByBa9Y9HSjfMPUgy6r
Tb6lgMgBoQKBgDmL9BYtuV92CCnpjITzFkt1bDrHhUIgaHz+EkEFbHi3uxiqxLko
E3etl/hKF3x+nY0OCYT69OzNLTYoVmtN2AM6z/us9qODxy/O+DuGZ4pnn0VGtPr/
ocHuEYWcZSSvT5JuKws5d3lWb9ftXSXZw33tzEXTtrxQvE8OhcD5CtK9AoGBAMk0
kqOwPKOd9egDXGIWaEx8PtQDWpgkcGE1c8Dpe8N9K3Ix874AcD8ITX5EcZnbeJZf
XUZSZVBhSHuebsUqqr0rd4LVmWo1tvDwtZ47UpkrPYUZgJO9gehTFtZ7EzQ7DEvm
CLUjzqSshQDrGpxGeLAGEgkOfO5TDv0XvjLTtk7BAoGBAM9ObVMPg+RhnVUY5oNT
2A+Qq/3sitcbaJ2JKCjJEhttF0fF+0VYXf8c1YNE1AOfA/YnEazfCvPEOVmXGAeq
iKf0FohQ1+dh9ShOK5tcR3jmMzrCwBJFlqjX942m/8FFg6B1za8nrrkSnWNCbJi5
rmSv7B4llshgzTeEKqgM6GX1
-----END PRIVATE KEY-----

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDnjCCAoagAwIBAgIUeKiEGBSfC/zsONwU0IW6Q9NgkPAwDQYJKoZIhvcNAQEL
BQAwajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G
A1UECgwGTk9ERUpTMTAwLgYDVQQDDCdOb2RlSlMtTm9uLVRydXN0ZWQtVGVzdC1J
bnRlcm1lZGlhdGUtQ0EwIBcNMjUwMjI3MDgxNzUwWhgPMjI5ODEyMTIwODE3NTBa
MEwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNV
BAoMBk5PREVKUzESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAshskMqfwX4J5IA0poqWfm2jF23rBDBFw5FTdZP/dbYrS
UCBOYqg5Jxgq4BxCnGq8ArGAQajOAAiwISK3h/WQ+XqaeEh5PmL4/dW3UZCvcR8I
NN7LCXPnQcvJu1G4VbBDm8WbkkmGJvy6553kA+8SXyeoEs3nXTqQWVINo/8alt6m
bRe2KA8FWgPrEUJgb+Vvl/z7a1V7PQSvWSuL0pBcj04tJQ5WrXAl72GI6eArJrM4
Yl7Z08ZeGsSKAN+9aFnFyBfRmUeHgDTI9OQjw6FcwArCXZRmaX3CyGZJYgL6DAyf
ukyyRXUT8Ii37W306Vp6d1prqZ4A2fih2sfbcpeLrwIDAQABo1gwVjAUBgNVHREE
DTALgglsb2NhbGhvc3QwHQYDVR0OBBYEFAa6wwZ2tpzJdeCtsG0sUw7MpG39MB8G
A1UdIwQYMBaAFH1pjDE6lilR7aMyg3QwCp4bgDwbMA0GCSqGSIb3DQEBCwUAA4IB
AQBWyVgyhKnRomPa23axktq8/8RC7h6mSJEOW+uTlwam/TqnWQFJspwosStOQFu4
pg7Ww9MtKJSr9/vxxsyvNaKH5ZNTtgqqlzfYzVLbfwOirNSx4Mp1izQ0G5mfx3Yj
+WEXarNaY8R0benqWMeArTFb9CdDcxvMcSdtkGrMXMuKXFN67zou8NQVkvGzc/tb
imS/Ur9goJYUPlg2xor+P09tiIT+pEG+bpjYZ0U/1D5lIjQYCmZiy9ECL3WBc4df
NKsJnlA2GZ4TXh2jFzQw3yZPSLCqNdy+9RdOB058wRYooaFYrOkRiUe9ZV5w1MW5
mVuwUmrRSI79K26jdTav44PZ
-----END CERTIFICATE-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCyGyQyp/Bfgnkg
DSmipZ+baMXbesEMEXDkVN1k/91titJQIE5iqDknGCrgHEKcarwCsYBBqM4ACLAh
IreH9ZD5epp4SHk+Yvj91bdRkK9xHwg03ssJc+dBy8m7UbhVsEObxZuSSYYm/Lrn
neQD7xJfJ6gSzeddOpBZUg2j/xqW3qZtF7YoDwVaA+sRQmBv5W+X/PtrVXs9BK9Z
K4vSkFyPTi0lDlatcCXvYYjp4CsmszhiXtnTxl4axIoA371oWcXIF9GZR4eANMj0
5CPDoVzACsJdlGZpfcLIZkliAvoMDJ+6TLJFdRPwiLftbfTpWnp3WmupngDZ+KHa
x9tyl4uvAgMBAAECggEAMKa1VpkFUjGjwJuX2fQAC0Wtdmyruw4wlk6QQ3yZEckv
9e89OjnVktZJL/rIP03wmZO/AzCHRP8ajZKcK6lqtptFAsJZTC9g8IWmk8NACVh+
t2J8d9KPQyvVqTODdPS3Ix/xhR5MZO34aDh7BpARpqiAgtJ39sF+mMePLlMLAlbO
U7/u1cttplvgiBRWTIiisyl9O+G2OCre1CXacEqkZ8jYWTP7sLofGCXCpgjBVKgl
8q4ktgPlREMVD/QW78CIdrKuOdmzV42zSeFfPoZjUC3nLCdIALquPJyBSSZvDEeA
T+eWSaIm5JcSTBjxG0f9riLQdup2Gz5NjPALHUTxMQKBgQDq2jyr1g0BUMFAJTQR
6LraWcCOz+7l/oH6WuFGm7gUBf5yrdykeWvd8cSfwZRm2tzoxVu44+M05X3ORMHR
wPyckITG9kWndzcOXpEOSiaObfqmEuz5gkpyzaUs5c9AE4pMhzIKNnruavPbD9Hy
4AiLIT3ssjAL14/cjFuZTXl/dQKBgQDCJMxq0jf2rtVfrPrpEh8CyNu4sUQs8O5t
9u4cvjGmHCfFpcdvCjS7gLuAZeFww3qjiv4pM0K5b7rjY3CelB+jlF2TG+4Jxf6h
y/9iPSN98i2FT4Jxc02GYxsPa3mYAxykmqqvIkak+2omaJake2tCyjE49QrfGx0r
TivZnwn+EwKBgQDe0a4MjqqKG/cuB94uO7PEZLE4DfooRl9Fi6H+3tE4VjOC1Ifp
mLYJvk+CDyTgrTg4tL8AXV59GltRL5UAkGxbkxYWuyN87rPSs1BG0X1hVuEfXgdt
9vrxj0Dupx8KOT/WudJ1NBlQSTMSHSFhoMMaVbCt+KVzJtL8OkLR4Vqr3QKBgAy8
MziSn58r6s1C4JanXKdnG5qq7ijwiQNnnkj+ZO1bjXRWopVzGvBtyl7qz/YArKvL
s05qkWbuoFjILhwI5WZqlhTPUTcM6N4eLpt4HTrmxvumsozUnnJBUAYb67cABUH6
71VbrzylTVpFpBQYEHoqHz54PIVUFv6/OvskhphHAoGAJukr8k+rvxXIXOjvgE2O
9sf2h7YZoW2AKK3tHPlG7XCuIFZJKKhkh+cVRorg/Ws5LLF/5egf234sfeZzdrvP
O2TA/0Hf4mhaJhn53E/PLSLEDVTzORs1L+PfLrFptrP2Eq7iAnbTwaWnjMfAcsy2
4ukRw65bBMLqv62KLTEZ5uk=
-----END PRIVATE KEY-----

View File

@ -19,9 +19,6 @@ test-fs-read-stream-concurrent-reads: PASS, FLAKY
# https://github.com/nodejs/build/issues/3043
test-snapshot-incompatible: SKIP
# Requires manual setup for certificates to be trusted by the system
test-native-certs: SKIP
[$system==win32]
# https://github.com/nodejs/node/issues/54808
test-async-context-frame: PASS, FLAKY

View File

@ -1,77 +0,0 @@
// Flags: --use-system-ca
import * as common from '../common/index.mjs';
import assert from 'node:assert/strict';
import https from 'node:https';
import fixtures from '../common/fixtures.js';
import { it, beforeEach, afterEach, describe } from 'node:test';
import { once } from 'events';
if (!common.hasCrypto) {
common.skip('requires crypto');
}
// To run this test, the system needs to be configured to trust
// the CA certificate first (which needs an interactive GUI approval, e.g. TouchID):
// On macOS:
// 1. To add the certificate:
// $ security add-trusted-cert \
// -k /Users/$USER/Library/Keychains/login.keychain-db \
// test/fixtures/keys/fake-startcom-root-cert.pem
// 2. To remove the certificate:
// $ security delete-certificate -c 'StartCom Certification Authority' \
// -t /Users/$USER/Library/Keychains/login.keychain-db
//
// On Windows:
// 1. To add the certificate in PowerShell (remember the thumbprint printed):
// $ Import-Certificate -FilePath .\test\fixtures\keys\fake-startcom-root-cert.cer \
// -CertStoreLocation Cert:\CurrentUser\Root
// 2. To remove the certificate by the thumbprint:
// $ $thumbprint = (Get-ChildItem -Path Cert:\CurrentUser\Root | \
// Where-Object { $_.Subject -match "StartCom Certification Authority" }).Thumbprint
// $ Remove-Item -Path "Cert:\CurrentUser\Root\$thumbprint"
//
// On Debian/Ubuntu:
// 1. To add the certificate:
// $ sudo cp test/fixtures/keys/fake-startcom-root-cert.pem \
// /usr/local/share/ca-certificates/fake-startcom-root-cert.crt
// $ sudo update-ca-certificates
// 2. To remove the certificate
// $ sudo rm /usr/local/share/ca-certificates/fake-startcom-root-cert.crt
// $ sudo update-ca-certificates --fresh
//
// For other Unix-like systems, consult their manuals, there are usually
// file-based processes similar to the Debian/Ubuntu one but with different
// file locations and update commands.
const handleRequest = (req, res) => {
const path = req.url;
switch (path) {
case '/hello-world':
res.writeHead(200);
res.end('hello world\n');
break;
default:
assert(false, `Unexpected path: ${path}`);
}
};
describe('use-system-ca', function() {
let server;
beforeEach(async function() {
server = https.createServer({
key: fixtures.readKey('agent8-key.pem'),
cert: fixtures.readKey('agent8-cert.pem'),
}, handleRequest);
server.listen(0);
await once(server, 'listening');
});
it('can connect successfully with a trusted certificate', async function() {
await fetch(`https://localhost:${server.address().port}/hello-world`);
});
afterEach(async function() {
server?.close();
});
});

92
test/system-ca/README.md Normal file
View File

@ -0,0 +1,92 @@
# system-ca
Tests for [--use-system-ca](../../doc/api/cli.md#--use-system-ca).
On both macOS and Windows interactive dialogs need confirming to add certificates to the OS trust store.
## macOS
**Adding the certificate**
```bash
security add-trusted-cert \
-k /Users/$USER/Library/Keychains/login.keychain-db \
test/fixtures/keys/fake-startcom-root-cert.pem
security add-certificates \
-k /Users/$USER/Library/Keychains/login.keychain-db \
test/fixtures/keys/intermediate-ca.pem
security add-certificates \
-k /Users/$USER/Library/Keychains/login.keychain-db \
test/fixtures/keys/non-trusted-intermediate-ca.pem
```
**Removing the certificate**
```bash
security delete-certificate -c 'StartCom Certification Authority' \
-t /Users/$USER/Library/Keychains/login.keychain-db
security delete-certificate -c 'NodeJS-Test-Intermediate-CA' \
-t /Users/$USER/Library/Keychains/login.keychain-db
security delete-certificate -c 'NodeJS-Non-Trusted-Test-Intermediate-CA' \
-t /Users/$USER/Library/Keychains/login.keychain-db
```
## Windows
**Adding the certificate**
Powershell:
```powershell
Import-Certificate -FilePath .\test\fixtures\keys\fake-startcom-root-cert.cer \
-CertStoreLocation Cert:\CurrentUser\Root
Import-Certificate -FilePath .\test\fixtures\keys\intermediate-ca.pem \
-CertStoreLocation Cert:\CurrentUser\CA
Import-Certificate -FilePath .\test\fixtures\keys\non-trusted-intermediate-ca.pem \
-CertStoreLocation Cert:\CurrentUser\CA
```
**Removing the certificate**
```powershell
$thumbprint = (Get-ChildItem -Path Cert:\CurrentUser\Root | \
Where-Object { $_.Subject -match "StartCom Certification Authority" }).Thumbprint
Remove-Item -Path "Cert:\CurrentUser\Root\$thumbprint"
$thumbprint = (Get-ChildItem -Path Cert:\CurrentUser\CA | \
Where-Object { $_.Subject -match "NodeJS-Test-Intermediate-CA" }).Thumbprint
Remove-Item -Path "Cert:\CurrentUser\CA\$thumbprint"
$thumbprint = (Get-ChildItem -Path Cert:\CurrentUser\CA | \
Where-Object { $_.Subject -match "NodeJS-Non-Trusted-Test-Intermediate-CA" }).Thumbprint
Remove-Item -Path "Cert:\CurrentUser\CA\$thumbprint"
```
## Debian/Ubuntu
**Adding the certificate**
```bash
sudo cp test/fixtures/keys/fake-startcom-root-cert.pem \
/usr/local/share/ca-certificates/fake-startcom-root-cert.crt
sudo cp test/fixtures/keys/intermediate-ca.pem \
/usr/local/share/ca-certificates/intermediate-ca.crt
sudo cp test/fixtures/keys/non-trusted-intermediate-ca.pem \
/usr/local/share/ca-certificates/non-trusted-intermediate-ca.crt
sudo update-ca-certificates
```
**Removing the certificate**
```bash
sudo rm /usr/local/share/ca-certificates/fake-startcom-root-cert.crt \
/usr/local/share/ca-certificates/intermediate-ca.crt \
/usr/local/share/ca-certificates/non-trusted-intermediate-ca.crt
sudo update-ca-certificates --fresh
```
## Other Unix-like systems
For other Unix-like systems, consult their manuals, there are usually
file-based processes similar to the Debian/Ubuntu one but with different
file locations and update commands.

View File

@ -0,0 +1,7 @@
prefix system-ca
# To mark a test as flaky, list the test name in the appropriate section
# below, without ".js", followed by ": PASS,FLAKY". Example:
# sample-test : PASS,FLAKY
[true] # This section applies to all platforms

View File

@ -0,0 +1,85 @@
// Flags: --use-system-ca
import * as common from '../common/index.mjs';
import assert from 'node:assert/strict';
import https from 'node:https';
import fixtures from '../common/fixtures.js';
import { it, beforeEach, afterEach, describe } from 'node:test';
import { once } from 'events';
if (!common.hasCrypto) {
common.skip('requires crypto');
}
// To run this test, the system needs to be configured to trust
// the CA certificate first (which needs an interactive GUI approval, e.g. TouchID):
// see the README.md in this folder for instructions on how to do this.
const handleRequest = (req, res) => {
const path = req.url;
switch (path) {
case '/hello-world':
res.writeHead(200);
res.end('hello world\n');
break;
default:
assert(false, `Unexpected path: ${path}`);
}
};
describe('use-system-ca', function() {
async function setupServer(key, cert) {
const theServer = https.createServer({
key: fixtures.readKey(key),
cert: fixtures.readKey(cert),
}, handleRequest);
theServer.listen(0);
await once(theServer, 'listening');
return theServer;
}
describe('signed with an intermediate CA certificate', () => {
let server;
beforeEach(async function() {
server = await setupServer('leaf-from-intermediate-key.pem', 'leaf-from-intermediate-cert.pem');
});
it('can connect successfully', async function() {
await fetch(`https://localhost:${server.address().port}/hello-world`);
});
afterEach(async function() {
server?.close();
});
});
describe('signed with a trusted intermediate but not trusted root CA certificate', () => {
let server;
beforeEach(async function() {
server = await setupServer(
'non-trusted-leaf-from-intermediate-key.pem',
'non-trusted-leaf-from-intermediate-cert.pem',
);
});
it('can connect successfully', async function() {
try {
await fetch(`https://localhost:${server.address().port}/hello-world`);
} catch (err) {
if (common.isWindows) {
assert.strictEqual(err.cause.code, 'UNABLE_TO_GET_ISSUER_CERT');
} else {
assert.strictEqual(err.cause.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
}
}
});
afterEach(async function() {
server?.close();
});
});
});

View File

@ -0,0 +1,55 @@
// Flags: --use-system-ca
import * as common from '../common/index.mjs';
import assert from 'node:assert/strict';
import https from 'node:https';
import fixtures from '../common/fixtures.js';
import { it, beforeEach, afterEach, describe } from 'node:test';
import { once } from 'events';
if (!common.hasCrypto) {
common.skip('requires crypto');
}
// To run this test, the system needs to be configured to trust
// the CA certificate first (which needs an interactive GUI approval, e.g. TouchID):
// see the README.md in this folder for instructions on how to do this.
const handleRequest = (req, res) => {
const path = req.url;
switch (path) {
case '/hello-world':
res.writeHead(200);
res.end('hello world\n');
break;
default:
assert(false, `Unexpected path: ${path}`);
}
};
describe('use-system-ca', function() {
async function setupServer(key, cert) {
const theServer = https.createServer({
key: fixtures.readKey(key),
cert: fixtures.readKey(cert),
}, handleRequest);
theServer.listen(0);
await once(theServer, 'listening');
return theServer;
}
let server;
beforeEach(async function() {
server = await setupServer('agent8-key.pem', 'agent8-cert.pem');
});
it('trusts a valid root certificate', async function() {
await fetch(`https://localhost:${server.address().port}/hello-world`);
});
afterEach(async function() {
server?.close();
});
});

View File

@ -0,0 +1,6 @@
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import testpy
def GetConfiguration(context, root):
return testpy.ParallelTestConfiguration(context, root, 'system-ca')

View File

@ -1586,6 +1586,7 @@ IGNORED_SUITES = [
'node-api',
'pummel',
'sqlite',
'system-ca',
'tick-processor',
'v8-updates'
]