node-opcua-server-configuration 2.168.0 → 2.169.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/server/file_transaction_manager.d.ts +10 -0
- package/dist/server/file_transaction_manager.js +23 -0
- package/dist/server/file_transaction_manager.js.map +1 -1
- package/dist/server/install_push_certificate_management.d.ts +1 -1
- package/dist/server/install_push_certificate_management.js +142 -1
- package/dist/server/install_push_certificate_management.js.map +1 -1
- package/dist/server/promote_trust_list.js +153 -1
- package/dist/server/promote_trust_list.js.map +1 -1
- package/dist/server/push_certificate_manager/create_signing_request.js +19 -13
- package/dist/server/push_certificate_manager/create_signing_request.js.map +1 -1
- package/dist/server/push_certificate_manager/update_certificate.js +19 -7
- package/dist/server/push_certificate_manager/update_certificate.js.map +1 -1
- package/dist/server/trust_list_server.js +5 -0
- package/dist/server/trust_list_server.js.map +1 -1
- package/package.json +23 -23
- package/source/index.ts +1 -0
- package/source/server/file_transaction_manager.ts +25 -0
- package/source/server/install_push_certificate_management.ts +175 -3
- package/source/server/promote_trust_list.ts +175 -1
- package/source/server/push_certificate_manager/create_signing_request.ts +26 -16
- package/source/server/push_certificate_manager/update_certificate.ts +23 -6
- package/source/server/trust_list_server.ts +5 -0
|
@@ -118,20 +118,30 @@ export async function executeCreateSigningRequest(
|
|
|
118
118
|
});
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
121
|
+
try {
|
|
122
|
+
const options = {
|
|
123
|
+
applicationUri: serverImpl.applicationUri,
|
|
124
|
+
subject: subjectName
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const activeCertificateManager = serverImpl.tmpCertificateManager || certificateManager;
|
|
128
|
+
|
|
129
|
+
await activeCertificateManager.initialize();
|
|
130
|
+
const csrFile = await activeCertificateManager.createCertificateRequest(options);
|
|
131
|
+
const csrPEM = await fs.promises.readFile(csrFile, "utf8");
|
|
132
|
+
const certificateSigningRequest = convertPEMtoDER(csrPEM);
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
certificateSigningRequest,
|
|
136
|
+
statusCode: StatusCodes.Good
|
|
137
|
+
};
|
|
138
|
+
} catch (err) {
|
|
139
|
+
errorLog(
|
|
140
|
+
"CreateSigningRequest failed during CSR generation:",
|
|
141
|
+
(err as Error).message,
|
|
142
|
+
"subject=", subjectName,
|
|
143
|
+
"applicationUri=", serverImpl.applicationUri
|
|
144
|
+
);
|
|
145
|
+
return { statusCode: StatusCodes.BadInternalError };
|
|
146
|
+
}
|
|
137
147
|
}
|
|
@@ -6,8 +6,10 @@ import type { CertificateManager, OPCUACertificateManager } from "node-opcua-cer
|
|
|
6
6
|
import { exploreCertificate, readPrivateKey } from "node-opcua-crypto";
|
|
7
7
|
import {
|
|
8
8
|
certificateMatchesPrivateKey,
|
|
9
|
+
type Certificate,
|
|
9
10
|
coercePEMorDerToPrivateKey,
|
|
10
11
|
coercePrivateKeyPem,
|
|
12
|
+
combine_der,
|
|
11
13
|
makeSHA1Thumbprint,
|
|
12
14
|
type PrivateKey,
|
|
13
15
|
toPem
|
|
@@ -52,18 +54,33 @@ async function preInstallIssuerCertificates(
|
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
// Helper: Stage main certificate to temporary files
|
|
57
|
+
//
|
|
58
|
+
// The PEM file contains the full chain (leaf + issuer CAs) so that
|
|
59
|
+
// getCertificateChain() returns the complete chain. This allows
|
|
60
|
+
// OpenSecureChannel and CreateSession to present the full chain to
|
|
61
|
+
// connecting clients, enabling them to build and verify the trust
|
|
62
|
+
// path without needing all CA certificates pre-installed.
|
|
55
63
|
async function preInstallCertificate(
|
|
56
64
|
serverImpl: PushCertificateManagerInternalContext,
|
|
57
65
|
certificateManager: CertificateManager,
|
|
58
|
-
certificate:
|
|
66
|
+
certificate: Certificate,
|
|
67
|
+
issuerCertificates?: Certificate[]
|
|
59
68
|
): Promise<void> {
|
|
60
69
|
const certFolder = certificateManager.ownCertFolder;
|
|
61
|
-
const destDER = path.join(certFolder, "certificate.der");
|
|
62
70
|
const destPEM = path.join(certFolder, "certificate.pem");
|
|
63
|
-
const certificatePEM = toPem(certificate, "CERTIFICATE");
|
|
64
71
|
|
|
65
|
-
|
|
72
|
+
// Build the full chain: leaf first, then issuer CAs
|
|
73
|
+
const certificateChain: Certificate[] = [certificate, ...(issuerCertificates ?? [])];
|
|
74
|
+
const certificatePEM = toPem(combine_der(certificateChain), "CERTIFICATE");
|
|
75
|
+
|
|
66
76
|
await serverImpl.fileTransactionManager.stageFile(destPEM, certificatePEM, "utf-8");
|
|
77
|
+
|
|
78
|
+
// Clean up any leftover certificate.der from previous installations.
|
|
79
|
+
// Since DER is no longer written, a stale file would be misleading.
|
|
80
|
+
const legacyDER = path.join(certFolder, "certificate.der");
|
|
81
|
+
if (fs.existsSync(legacyDER)) {
|
|
82
|
+
serverImpl.fileTransactionManager.stageFileRemoval(legacyDER);
|
|
83
|
+
}
|
|
67
84
|
}
|
|
68
85
|
|
|
69
86
|
// Helper: Stage private key to temporary file
|
|
@@ -164,7 +181,7 @@ export async function executeUpdateCertificate(
|
|
|
164
181
|
}
|
|
165
182
|
|
|
166
183
|
await preInstallIssuerCertificates(serverImpl, certificateManager, issuerCertificates);
|
|
167
|
-
await preInstallCertificate(serverImpl, certificateManager, certificate);
|
|
184
|
+
await preInstallCertificate(serverImpl, certificateManager, certificate, issuerCertificates);
|
|
168
185
|
serverImpl.emit("certificateUpdated", certificateGroupId, certificate);
|
|
169
186
|
return { statusCode: StatusCodes.Good, applyChangesRequired: true };
|
|
170
187
|
} else {
|
|
@@ -203,7 +220,7 @@ export async function executeUpdateCertificate(
|
|
|
203
220
|
|
|
204
221
|
await preInstallPrivateKey(serverImpl, certificateManager, privateKeyFormat, tempPrivateKey);
|
|
205
222
|
await preInstallIssuerCertificates(serverImpl, certificateManager, issuerCertificates);
|
|
206
|
-
await preInstallCertificate(serverImpl, certificateManager, certificate);
|
|
223
|
+
await preInstallCertificate(serverImpl, certificateManager, certificate, issuerCertificates);
|
|
207
224
|
|
|
208
225
|
serverImpl.emit("certificateUpdated", certificateGroupId, certificate);
|
|
209
226
|
return { statusCode: StatusCodes.Good, applyChangesRequired: true };
|
|
@@ -22,6 +22,11 @@ async function readAll(folder: string): Promise<Buffer[]> {
|
|
|
22
22
|
const ext = path.extname(file);
|
|
23
23
|
if (ext === ".der" || ext === ".pem") {
|
|
24
24
|
const chain = await readCertificateChainAsync(file);
|
|
25
|
+
// Return the full chain as a single ByteString.
|
|
26
|
+
// When addTrustedCertificateFromChain stores a chain-on-disk
|
|
27
|
+
// (leaf + issuer CAs in a single PEM), we preserve that
|
|
28
|
+
// chain so clients reading the TrustList can use it for
|
|
29
|
+
// chain-building.
|
|
25
30
|
const concatenated = Buffer.concat(chain);
|
|
26
31
|
results.push(concatenated);
|
|
27
32
|
} else if (ext === ".crl") {
|