node-opcua-pki 6.10.2 → 6.11.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/bin/pki.mjs +505 -119
- package/dist/bin/pki.mjs.map +1 -1
- package/dist/index.d.mts +217 -8
- package/dist/index.d.ts +217 -8
- package/dist/index.js +637 -261
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +642 -263
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/readme.md +27 -163
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-opcua-pki",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.11.0",
|
|
4
4
|
"description": "PKI management for node-opcua",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"wget-improved-2": "^3.3.0",
|
|
51
51
|
"yauzl": "^3.2.1"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "5536a27b3932c970505bee5fc5152424d6f16ea9"
|
|
54
54
|
}
|
package/readme.md
CHANGED
|
@@ -190,182 +190,46 @@ pki demo [--dev] [--silent] [--clean]
|
|
|
190
190
|
## Programmatic Usage
|
|
191
191
|
|
|
192
192
|
```typescript
|
|
193
|
-
import { CertificateManager } from "node-opcua-pki";
|
|
194
|
-
|
|
195
|
-
const cm = new CertificateManager({
|
|
196
|
-
location: "./my_pki",
|
|
197
|
-
keySize: 2048,
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
await cm.initialize();
|
|
201
|
-
|
|
202
|
-
// Create a self-signed certificate
|
|
203
|
-
await cm.createSelfSignedCertificate({
|
|
204
|
-
applicationUri: "urn:my-server:application",
|
|
205
|
-
subject: "/CN=My Server/O=My Organization",
|
|
206
|
-
dns: ["localhost"],
|
|
207
|
-
startDate: new Date(),
|
|
208
|
-
validity: 365,
|
|
209
|
-
});
|
|
193
|
+
import { CertificateManager, CertificateAuthority } from "node-opcua-pki";
|
|
210
194
|
```
|
|
211
195
|
|
|
212
|
-
### CertificateManager
|
|
213
|
-
|
|
214
|
-
#### Certificate Trust
|
|
215
|
-
|
|
216
|
-
| Method | Description |
|
|
217
|
-
| ----------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
218
|
-
| `trustCertificate(cert)` | Add a certificate to the trusted store |
|
|
219
|
-
| `rejectCertificate(cert)` | Move a certificate to the rejected store |
|
|
220
|
-
| `verifyCertificate(cert, options?)` | Full certificate chain validation |
|
|
221
|
-
| `removeTrustedCertificate(thumbprint)` | Remove a trusted certificate by SHA-1 thumbprint. Returns the certificate buffer or `null` |
|
|
222
|
-
| `addTrustedCertificateFromChain(certChain)` | Validate and trust the leaf certificate from a DER chain |
|
|
223
|
-
| `isIssuerInUseByTrustedCertificate(issuerCert)` | Check if any trusted cert was signed by this issuer |
|
|
224
|
-
| `reloadCertificates()` | Force a full re-scan of all PKI folders |
|
|
225
|
-
|
|
226
|
-
#### Issuer (CA) Certificates
|
|
227
|
-
|
|
228
|
-
| Method | Description |
|
|
229
|
-
| --------------------------------------------- | ------------------------------------------------------------------------ |
|
|
230
|
-
| `addIssuer(cert, validate?, addInTrustList?)` | Add a CA certificate to the issuers store |
|
|
231
|
-
| `hasIssuer(thumbprint)` | Check if an issuer exists by SHA-1 thumbprint |
|
|
232
|
-
| `removeIssuer(thumbprint)` | Remove an issuer by thumbprint. Returns the certificate buffer or `null` |
|
|
233
|
-
| `findIssuerCertificate(cert)` | Find the issuer certificate for a given certificate |
|
|
234
|
-
|
|
235
|
-
#### Certificate Revocation Lists (CRLs)
|
|
196
|
+
### [CertificateManager](./docs/certificate-manager.md)
|
|
236
197
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
| `addRevocationList(crl, target?)` | Add a CRL. `target` is `"issuers"` (default) or `"trusted"` |
|
|
240
|
-
| `clearRevocationLists(target)` | Remove all CRLs from `"issuers"`, `"trusted"`, or `"all"` |
|
|
241
|
-
| `removeRevocationListsForIssuer(cert, target?)` | Remove CRLs issued by a specific CA. `target`: `"issuers"`, `"trusted"`, or `"all"` (default) |
|
|
242
|
-
| `isCertificateRevoked(cert, issuerCert?)` | Check if a certificate has been revoked |
|
|
243
|
-
|
|
244
|
-
#### Folder Accessors
|
|
245
|
-
|
|
246
|
-
| Getter | Path |
|
|
247
|
-
| ------------------- | -------------------------- |
|
|
248
|
-
| `trustedFolder` | `{location}/trusted/certs` |
|
|
249
|
-
| `rejectedFolder` | `{location}/rejected` |
|
|
250
|
-
| `crlFolder` | `{location}/trusted/crl` |
|
|
251
|
-
| `issuersCertFolder` | `{location}/issuers/certs` |
|
|
252
|
-
| `issuersCrlFolder` | `{location}/issuers/crl` |
|
|
253
|
-
| `rootDir` | `{location}` |
|
|
254
|
-
|
|
255
|
-
### CertificateAuthority API
|
|
256
|
-
|
|
257
|
-
The `CertificateAuthority` class manages an OpenSSL-based CA directory structure for issuing, revoking, and tracking certificates.
|
|
198
|
+
Manages an OPC UA–compliant PKI directory with trust stores, issuer
|
|
199
|
+
stores, file watching, and certificate lifecycle.
|
|
258
200
|
|
|
259
201
|
```typescript
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const ca = new CertificateAuthority({
|
|
263
|
-
location: "./my_ca",
|
|
264
|
-
keySize: 2048,
|
|
265
|
-
});
|
|
266
|
-
await ca.initialize();
|
|
202
|
+
const cm = new CertificateManager({ location: "./my_pki" });
|
|
203
|
+
await cm.initialize();
|
|
267
204
|
```
|
|
268
205
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
| Method | Returns | Description |
|
|
272
|
-
| ------------------------ | -------- | ---------------------------------------- |
|
|
273
|
-
| `getCACertificateDER()` | `Buffer` | CA certificate as DER |
|
|
274
|
-
| `getCACertificatePEM()` | `string` | CA certificate as PEM |
|
|
275
|
-
| `getCRLDER()` | `Buffer` | Current CRL as DER (empty if none) |
|
|
276
|
-
| `getCRLPEM()` | `string` | Current CRL as PEM |
|
|
206
|
+
### [CertificateAuthority](./docs/certificate-authority.md)
|
|
277
207
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
| `signCertificateRequestFromDER(csrDer, options?)` | `Promise<Buffer>` | Sign a DER-encoded CSR, return signed cert as DER. Handles temp files internally. |
|
|
283
|
-
| `revokeCertificateDER(certDer, reason?)` | `Promise<void>` | Revoke a DER-encoded certificate. Looks up the stored cert by serial number. |
|
|
208
|
+
OpenSSL-based CA for issuing, revoking, and tracking certificates.
|
|
209
|
+
Supports root CAs, intermediate CAs with manual 3-step workflow,
|
|
210
|
+
proactive certificate renewal, and full chain output per OPC UA
|
|
211
|
+
Part 6 §6.2.6.
|
|
284
212
|
|
|
285
213
|
```typescript
|
|
286
|
-
//
|
|
287
|
-
const
|
|
288
|
-
|
|
214
|
+
// Root CA
|
|
215
|
+
const rootCA = new CertificateAuthority({
|
|
216
|
+
keySize: 2048,
|
|
217
|
+
location: "./my_root_ca",
|
|
218
|
+
subject: "/CN=My Root CA",
|
|
289
219
|
});
|
|
220
|
+
await rootCA.initialize();
|
|
290
221
|
|
|
291
|
-
//
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
These methods parse the OpenSSL `index.txt` database to query issued certificate status. Certificate files are read from the CA's `certs/` directory.
|
|
298
|
-
|
|
299
|
-
| Method | Returns | Description |
|
|
300
|
-
| --- | --- | --- |
|
|
301
|
-
| `getIssuedCertificates()` | `IssuedCertificateRecord[]` | All records from `index.txt` |
|
|
302
|
-
| `getIssuedCertificateCount()` | `number` | Total number of issued certificates |
|
|
303
|
-
| `getCertificateStatus(serial)` | `string \| undefined` | `"valid"`, `"revoked"`, or `"expired"` |
|
|
304
|
-
| `getCertificateBySerial(serial)` | `Buffer \| undefined` | DER buffer from `certs/<serial>.pem` |
|
|
305
|
-
|
|
306
|
-
```typescript
|
|
307
|
-
// List all issued certificates
|
|
308
|
-
const records = ca.getIssuedCertificates();
|
|
309
|
-
for (const r of records) {
|
|
310
|
-
console.log(`${r.serial}: ${r.status} — ${r.subject}`);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Check if a specific certificate is revoked
|
|
314
|
-
const status = ca.getCertificateStatus("1000");
|
|
315
|
-
if (status === "revoked") {
|
|
316
|
-
console.log("Certificate 1000 has been revoked");
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Read a certificate by serial number
|
|
320
|
-
const der = ca.getCertificateBySerial("1000");
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
**`IssuedCertificateRecord`** fields:
|
|
324
|
-
|
|
325
|
-
| Field | Type | Description |
|
|
326
|
-
| --- | --- | --- |
|
|
327
|
-
| `serial` | `string` | Hex serial (e.g. `"1000"`) |
|
|
328
|
-
| `status` | `"valid" \| "revoked" \| "expired"` | Certificate status |
|
|
329
|
-
| `subject` | `string` | X.500 subject (slash-delimited) |
|
|
330
|
-
| `expiryDate` | `string` | ISO-8601 expiry date |
|
|
331
|
-
| `revocationDate` | `string?` | ISO-8601 revocation date (if revoked) |
|
|
332
|
-
|
|
333
|
-
### File Watching
|
|
334
|
-
|
|
335
|
-
`CertificateManager` uses [chokidar](https://github.com/paulmillr/chokidar) to watch the PKI folders for changes. By default, it uses **native OS events** (inotify, FSEvents, ReadDirectoryChangesW) for near-real-time detection.
|
|
336
|
-
|
|
337
|
-
#### Environment Variables
|
|
338
|
-
|
|
339
|
-
| Variable | Description | Default |
|
|
340
|
-
| --- | --- | --- |
|
|
341
|
-
| `OPCUA_PKI_USE_POLLING` | Set to `"true"` to use polling instead of native FS events. Required for NFS, CIFS, Docker volumes, or other remote/virtual file systems. | `false` |
|
|
342
|
-
| `OPCUA_PKI_POLLING_INTERVAL` | Polling interval in milliseconds (only effective when polling is enabled). Clamped to [100, 600 000]. | `5000` |
|
|
343
|
-
|
|
344
|
-
```bash
|
|
345
|
-
# Example: enable polling with a 2-second interval
|
|
346
|
-
OPCUA_PKI_USE_POLLING=true OPCUA_PKI_POLLING_INTERVAL=2000 node my_server.js
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
> **Note:** If external processes modify the PKI folders directly (e.g., CLI tools, OPC UA `WriteTrustList`), call `reloadCertificates()` to force an immediate re-scan of the folder state.
|
|
350
|
-
|
|
351
|
-
#### Events
|
|
352
|
-
|
|
353
|
-
After `initialize()`, the `CertificateManager` emits events when its file-system watchers detect live changes. Events are **not** emitted during `initialize()` or `reloadCertificates()` to avoid noise.
|
|
354
|
-
|
|
355
|
-
| Event | Payload | Description |
|
|
356
|
-
| --- | --- | --- |
|
|
357
|
-
| `certificateAdded` | `{ store, certificate, fingerprint, filename }` | A certificate file was added to a store |
|
|
358
|
-
| `certificateRemoved` | `{ store, fingerprint, filename }` | A certificate file was removed from a store |
|
|
359
|
-
| `certificateChange` | `{ store, certificate, fingerprint, filename }` | A certificate file was modified in a store |
|
|
360
|
-
| `crlAdded` | `{ store, filename }` | A CRL file was added |
|
|
361
|
-
| `crlRemoved` | `{ store, filename }` | A CRL file was removed |
|
|
362
|
-
|
|
363
|
-
`store` is one of `"trusted"`, `"rejected"`, `"issuersCerts"` (for certificate events) or `"crl"`, `"issuersCrl"` (for CRL events).
|
|
364
|
-
|
|
365
|
-
```typescript
|
|
366
|
-
cm.on("certificateAdded", ({ store, fingerprint, filename }) => {
|
|
367
|
-
console.log(`New certificate in ${store}: ${fingerprint}`);
|
|
222
|
+
// Intermediate CA (3-step workflow)
|
|
223
|
+
const intCA = new CertificateAuthority({
|
|
224
|
+
keySize: 2048,
|
|
225
|
+
location: "./my_intermediate_ca",
|
|
226
|
+
subject: "/CN=My Intermediate CA",
|
|
368
227
|
});
|
|
228
|
+
const result = await intCA.initializeCSR(); // Step 1
|
|
229
|
+
await rootCA.signCACertificateRequest( // Step 2
|
|
230
|
+
certFile, result.csrPath, { validity: 3650 }
|
|
231
|
+
);
|
|
232
|
+
await intCA.installCACertificate(certFile); // Step 3
|
|
369
233
|
```
|
|
370
234
|
|
|
371
235
|
## References
|