node-opcua-pki 6.12.2 → 6.14.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 +93 -8
- package/dist/bin/pki.mjs.map +1 -1
- package/dist/index.d.mts +60 -1
- package/dist/index.d.ts +60 -1
- package/dist/index.js +94 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +93 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -671,6 +671,20 @@ interface CertificateManagerOptions {
|
|
|
671
671
|
* Defaults are secure — all checks enabled.
|
|
672
672
|
*/
|
|
673
673
|
addCertificateValidationOptions?: AddCertificateValidationOptions;
|
|
674
|
+
/**
|
|
675
|
+
* When `true`, the CertificateManager will **not** start
|
|
676
|
+
* chokidar file-system watchers on the PKI folders.
|
|
677
|
+
*
|
|
678
|
+
* The initial file-system scan still runs so the in-memory
|
|
679
|
+
* indexes are populated, but live change detection is
|
|
680
|
+
* disabled. This is useful in test / CI environments where
|
|
681
|
+
* many CertificateManager instances are created in parallel
|
|
682
|
+
* and the accumulated `fs.watch` handles exhaust the libuv
|
|
683
|
+
* thread-pool, causing event-loop starvation.
|
|
684
|
+
*
|
|
685
|
+
* @defaultValue false
|
|
686
|
+
*/
|
|
687
|
+
disableFileWatchers?: boolean;
|
|
674
688
|
}
|
|
675
689
|
/**
|
|
676
690
|
* Parameters for {@link createSelfSignedCertificate}.
|
|
@@ -857,6 +871,33 @@ declare enum CertificateManagerState {
|
|
|
857
871
|
* await cm.dispose();
|
|
858
872
|
* ```
|
|
859
873
|
*/
|
|
874
|
+
/**
|
|
875
|
+
* Status codes returned by {@link CertificateManager.completeCertificateChain}.
|
|
876
|
+
*/
|
|
877
|
+
declare enum ChainCompletionStatus {
|
|
878
|
+
/** The chain already reached a self-signed root — no action was needed. */
|
|
879
|
+
AlreadyComplete = "AlreadyComplete",
|
|
880
|
+
/** One or more issuer certificates were successfully appended. */
|
|
881
|
+
ChainCompleted = "ChainCompleted",
|
|
882
|
+
/** The issuer for the last certificate in the chain could not be found
|
|
883
|
+
* in the issuers or trusted stores. The chain is still partial. */
|
|
884
|
+
IssuerNotFound = "IssuerNotFound",
|
|
885
|
+
/** The input chain was empty. */
|
|
886
|
+
EmptyChain = "EmptyChain",
|
|
887
|
+
/** Chain completion was stopped because the maximum depth was reached. */
|
|
888
|
+
MaxDepthReached = "MaxDepthReached"
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Result of {@link CertificateManager.completeCertificateChain}.
|
|
892
|
+
*/
|
|
893
|
+
interface ChainCompletionResult {
|
|
894
|
+
/** The (possibly completed) certificate chain, leaf first. */
|
|
895
|
+
chain: Certificate[];
|
|
896
|
+
/** Status code indicating whether completion succeeded and why/why not. */
|
|
897
|
+
status: ChainCompletionStatus;
|
|
898
|
+
/** Human-readable diagnostic message. */
|
|
899
|
+
message: string;
|
|
900
|
+
}
|
|
860
901
|
declare class CertificateManager extends EventEmitter {
|
|
861
902
|
#private;
|
|
862
903
|
/**
|
|
@@ -1150,6 +1191,24 @@ declare class CertificateManager extends EventEmitter {
|
|
|
1150
1191
|
*
|
|
1151
1192
|
*/
|
|
1152
1193
|
findIssuerCertificate(certificate: Certificate | Certificate[]): Promise<Certificate | null>;
|
|
1194
|
+
/**
|
|
1195
|
+
* Outcome status for {@link CertificateManager.completeCertificateChain}.
|
|
1196
|
+
*/
|
|
1197
|
+
static readonly ChainCompletionStatus: typeof ChainCompletionStatus;
|
|
1198
|
+
/**
|
|
1199
|
+
* Complete a certificate chain by walking the issuer store.
|
|
1200
|
+
*
|
|
1201
|
+
* Starting from the last certificate in the provided chain, this method
|
|
1202
|
+
* repeatedly calls {@link findIssuerCertificate} to locate the parent
|
|
1203
|
+
* certificate until it reaches a self-signed root or can no longer find
|
|
1204
|
+
* an issuer.
|
|
1205
|
+
*
|
|
1206
|
+
* @param chain - the (potentially partial) certificate chain, leaf first
|
|
1207
|
+
* @param maxDepth - maximum number of issuers to append (default: 10)
|
|
1208
|
+
* @returns a {@link ChainCompletionResult} containing the (possibly completed)
|
|
1209
|
+
* chain, a status code, and an optional diagnostic message.
|
|
1210
|
+
*/
|
|
1211
|
+
completeCertificateChain(chain: Certificate[], maxDepth?: number): Promise<ChainCompletionResult>;
|
|
1153
1212
|
/**
|
|
1154
1213
|
* Check whether a certificate has been revoked by its issuer's CRL.
|
|
1155
1214
|
*
|
|
@@ -1305,4 +1364,4 @@ declare function dumpPFX(pfxFile: Filename, passphrase?: string): Promise<string
|
|
|
1305
1364
|
*/
|
|
1306
1365
|
declare function install_prerequisite(): Promise<string>;
|
|
1307
1366
|
|
|
1308
|
-
export { type AddCertificateValidationOptions, CertificateAuthority, type CertificateAuthorityOptions, CertificateManager, type CertificateManagerEvents, type CertificateManagerOptions, CertificateManagerState, type CertificateStatus, type CertificateStore, type CreateCertificateSigningRequestOptions, type CreateCertificateSigningRequestWithConfigOptions, type CreatePFXOptions, type CreateSelfSignCertificateParam, type CreateSelfSignCertificateParam1, type CreateSelfSignCertificateWithConfigParam, type CrlStore, type ExtractPFXOptions, type ExtractPFXResult, type Filename, type GenerateKeyPairAndSignOptions, type GenerateKeyPairAndSignPFXOptions, type InitializeCSRResult, type InstallCACertificateResult, type KeyLength, type KeySize, type Params, type ProcessAltNamesParam, type SignCertificateOptions, type StartDateEndDateParam, type Thumbprint, VerificationStatus, type VerifyCertificateOptions, adjustApplicationUri, adjustDate, coerceCertificateChain, convertPFXtoPEM, createPFX, dumpPFX, extractAllFromPFX, extractCACertificatesFromPFX, extractCertificateFromPFX, extractPrivateKeyFromPFX, findIssuerCertificateInChain, install_prerequisite, isIntermediateIssuer, isIssuer, isRootIssuer, makeFingerprint, quote };
|
|
1367
|
+
export { type AddCertificateValidationOptions, CertificateAuthority, type CertificateAuthorityOptions, CertificateManager, type CertificateManagerEvents, type CertificateManagerOptions, CertificateManagerState, type CertificateStatus, type CertificateStore, type ChainCompletionResult, ChainCompletionStatus, type CreateCertificateSigningRequestOptions, type CreateCertificateSigningRequestWithConfigOptions, type CreatePFXOptions, type CreateSelfSignCertificateParam, type CreateSelfSignCertificateParam1, type CreateSelfSignCertificateWithConfigParam, type CrlStore, type ExtractPFXOptions, type ExtractPFXResult, type Filename, type GenerateKeyPairAndSignOptions, type GenerateKeyPairAndSignPFXOptions, type InitializeCSRResult, type InstallCACertificateResult, type KeyLength, type KeySize, type Params, type ProcessAltNamesParam, type SignCertificateOptions, type StartDateEndDateParam, type Thumbprint, VerificationStatus, type VerifyCertificateOptions, adjustApplicationUri, adjustDate, coerceCertificateChain, convertPFXtoPEM, createPFX, dumpPFX, extractAllFromPFX, extractCACertificatesFromPFX, extractCertificateFromPFX, extractPrivateKeyFromPFX, findIssuerCertificateInChain, install_prerequisite, isIntermediateIssuer, isIssuer, isRootIssuer, makeFingerprint, quote };
|
package/dist/index.d.ts
CHANGED
|
@@ -671,6 +671,20 @@ interface CertificateManagerOptions {
|
|
|
671
671
|
* Defaults are secure — all checks enabled.
|
|
672
672
|
*/
|
|
673
673
|
addCertificateValidationOptions?: AddCertificateValidationOptions;
|
|
674
|
+
/**
|
|
675
|
+
* When `true`, the CertificateManager will **not** start
|
|
676
|
+
* chokidar file-system watchers on the PKI folders.
|
|
677
|
+
*
|
|
678
|
+
* The initial file-system scan still runs so the in-memory
|
|
679
|
+
* indexes are populated, but live change detection is
|
|
680
|
+
* disabled. This is useful in test / CI environments where
|
|
681
|
+
* many CertificateManager instances are created in parallel
|
|
682
|
+
* and the accumulated `fs.watch` handles exhaust the libuv
|
|
683
|
+
* thread-pool, causing event-loop starvation.
|
|
684
|
+
*
|
|
685
|
+
* @defaultValue false
|
|
686
|
+
*/
|
|
687
|
+
disableFileWatchers?: boolean;
|
|
674
688
|
}
|
|
675
689
|
/**
|
|
676
690
|
* Parameters for {@link createSelfSignedCertificate}.
|
|
@@ -857,6 +871,33 @@ declare enum CertificateManagerState {
|
|
|
857
871
|
* await cm.dispose();
|
|
858
872
|
* ```
|
|
859
873
|
*/
|
|
874
|
+
/**
|
|
875
|
+
* Status codes returned by {@link CertificateManager.completeCertificateChain}.
|
|
876
|
+
*/
|
|
877
|
+
declare enum ChainCompletionStatus {
|
|
878
|
+
/** The chain already reached a self-signed root — no action was needed. */
|
|
879
|
+
AlreadyComplete = "AlreadyComplete",
|
|
880
|
+
/** One or more issuer certificates were successfully appended. */
|
|
881
|
+
ChainCompleted = "ChainCompleted",
|
|
882
|
+
/** The issuer for the last certificate in the chain could not be found
|
|
883
|
+
* in the issuers or trusted stores. The chain is still partial. */
|
|
884
|
+
IssuerNotFound = "IssuerNotFound",
|
|
885
|
+
/** The input chain was empty. */
|
|
886
|
+
EmptyChain = "EmptyChain",
|
|
887
|
+
/** Chain completion was stopped because the maximum depth was reached. */
|
|
888
|
+
MaxDepthReached = "MaxDepthReached"
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Result of {@link CertificateManager.completeCertificateChain}.
|
|
892
|
+
*/
|
|
893
|
+
interface ChainCompletionResult {
|
|
894
|
+
/** The (possibly completed) certificate chain, leaf first. */
|
|
895
|
+
chain: Certificate[];
|
|
896
|
+
/** Status code indicating whether completion succeeded and why/why not. */
|
|
897
|
+
status: ChainCompletionStatus;
|
|
898
|
+
/** Human-readable diagnostic message. */
|
|
899
|
+
message: string;
|
|
900
|
+
}
|
|
860
901
|
declare class CertificateManager extends EventEmitter {
|
|
861
902
|
#private;
|
|
862
903
|
/**
|
|
@@ -1150,6 +1191,24 @@ declare class CertificateManager extends EventEmitter {
|
|
|
1150
1191
|
*
|
|
1151
1192
|
*/
|
|
1152
1193
|
findIssuerCertificate(certificate: Certificate | Certificate[]): Promise<Certificate | null>;
|
|
1194
|
+
/**
|
|
1195
|
+
* Outcome status for {@link CertificateManager.completeCertificateChain}.
|
|
1196
|
+
*/
|
|
1197
|
+
static readonly ChainCompletionStatus: typeof ChainCompletionStatus;
|
|
1198
|
+
/**
|
|
1199
|
+
* Complete a certificate chain by walking the issuer store.
|
|
1200
|
+
*
|
|
1201
|
+
* Starting from the last certificate in the provided chain, this method
|
|
1202
|
+
* repeatedly calls {@link findIssuerCertificate} to locate the parent
|
|
1203
|
+
* certificate until it reaches a self-signed root or can no longer find
|
|
1204
|
+
* an issuer.
|
|
1205
|
+
*
|
|
1206
|
+
* @param chain - the (potentially partial) certificate chain, leaf first
|
|
1207
|
+
* @param maxDepth - maximum number of issuers to append (default: 10)
|
|
1208
|
+
* @returns a {@link ChainCompletionResult} containing the (possibly completed)
|
|
1209
|
+
* chain, a status code, and an optional diagnostic message.
|
|
1210
|
+
*/
|
|
1211
|
+
completeCertificateChain(chain: Certificate[], maxDepth?: number): Promise<ChainCompletionResult>;
|
|
1153
1212
|
/**
|
|
1154
1213
|
* Check whether a certificate has been revoked by its issuer's CRL.
|
|
1155
1214
|
*
|
|
@@ -1305,4 +1364,4 @@ declare function dumpPFX(pfxFile: Filename, passphrase?: string): Promise<string
|
|
|
1305
1364
|
*/
|
|
1306
1365
|
declare function install_prerequisite(): Promise<string>;
|
|
1307
1366
|
|
|
1308
|
-
export { type AddCertificateValidationOptions, CertificateAuthority, type CertificateAuthorityOptions, CertificateManager, type CertificateManagerEvents, type CertificateManagerOptions, CertificateManagerState, type CertificateStatus, type CertificateStore, type CreateCertificateSigningRequestOptions, type CreateCertificateSigningRequestWithConfigOptions, type CreatePFXOptions, type CreateSelfSignCertificateParam, type CreateSelfSignCertificateParam1, type CreateSelfSignCertificateWithConfigParam, type CrlStore, type ExtractPFXOptions, type ExtractPFXResult, type Filename, type GenerateKeyPairAndSignOptions, type GenerateKeyPairAndSignPFXOptions, type InitializeCSRResult, type InstallCACertificateResult, type KeyLength, type KeySize, type Params, type ProcessAltNamesParam, type SignCertificateOptions, type StartDateEndDateParam, type Thumbprint, VerificationStatus, type VerifyCertificateOptions, adjustApplicationUri, adjustDate, coerceCertificateChain, convertPFXtoPEM, createPFX, dumpPFX, extractAllFromPFX, extractCACertificatesFromPFX, extractCertificateFromPFX, extractPrivateKeyFromPFX, findIssuerCertificateInChain, install_prerequisite, isIntermediateIssuer, isIssuer, isRootIssuer, makeFingerprint, quote };
|
|
1367
|
+
export { type AddCertificateValidationOptions, CertificateAuthority, type CertificateAuthorityOptions, CertificateManager, type CertificateManagerEvents, type CertificateManagerOptions, CertificateManagerState, type CertificateStatus, type CertificateStore, type ChainCompletionResult, ChainCompletionStatus, type CreateCertificateSigningRequestOptions, type CreateCertificateSigningRequestWithConfigOptions, type CreatePFXOptions, type CreateSelfSignCertificateParam, type CreateSelfSignCertificateParam1, type CreateSelfSignCertificateWithConfigParam, type CrlStore, type ExtractPFXOptions, type ExtractPFXResult, type Filename, type GenerateKeyPairAndSignOptions, type GenerateKeyPairAndSignPFXOptions, type InitializeCSRResult, type InstallCACertificateResult, type KeyLength, type KeySize, type Params, type ProcessAltNamesParam, type SignCertificateOptions, type StartDateEndDateParam, type Thumbprint, VerificationStatus, type VerifyCertificateOptions, adjustApplicationUri, adjustDate, coerceCertificateChain, convertPFXtoPEM, createPFX, dumpPFX, extractAllFromPFX, extractCACertificatesFromPFX, extractCertificateFromPFX, extractPrivateKeyFromPFX, findIssuerCertificateInChain, install_prerequisite, isIntermediateIssuer, isIssuer, isRootIssuer, makeFingerprint, quote };
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __export(lib_exports, {
|
|
|
33
33
|
CertificateAuthority: () => CertificateAuthority,
|
|
34
34
|
CertificateManager: () => CertificateManager,
|
|
35
35
|
CertificateManagerState: () => CertificateManagerState,
|
|
36
|
+
ChainCompletionStatus: () => ChainCompletionStatus,
|
|
36
37
|
Subject: () => import_node_opcua_crypto.Subject,
|
|
37
38
|
VerificationStatus: () => VerificationStatus,
|
|
38
39
|
adjustApplicationUri: () => adjustApplicationUri,
|
|
@@ -853,15 +854,16 @@ nsComment = "CA Generated by Node-OPCUA Certificate utility usin
|
|
|
853
854
|
subjectKeyIdentifier = hash
|
|
854
855
|
basicConstraints = CA:TRUE
|
|
855
856
|
keyUsage = critical, cRLSign, keyCertSign
|
|
857
|
+
subjectAltName = $ENV::ALTNAME
|
|
856
858
|
nsComment = "CA CSR generated by Node-OPCUA Certificate utility using openssl"
|
|
857
859
|
[ v3_ca ]
|
|
858
860
|
subjectKeyIdentifier = hash
|
|
859
861
|
authorityKeyIdentifier = keyid:always,issuer:always
|
|
860
862
|
basicConstraints = CA:TRUE
|
|
861
863
|
keyUsage = critical, cRLSign, keyCertSign
|
|
864
|
+
subjectAltName = $ENV::ALTNAME
|
|
862
865
|
nsComment = "CA Certificate generated by Node-OPCUA Certificate utility using openssl"
|
|
863
866
|
#nsCertType = sslCA, emailCA
|
|
864
|
-
#subjectAltName = email:copy
|
|
865
867
|
#issuerAltName = issuer:copy
|
|
866
868
|
#obj = DER:02:03
|
|
867
869
|
crlDistributionPoints = @crl_info
|
|
@@ -948,7 +950,8 @@ async function construct_CertificateAuthority(certificateAuthority) {
|
|
|
948
950
|
await import_node_fs7.default.promises.writeFile(caConfigFile, data);
|
|
949
951
|
}
|
|
950
952
|
const subjectOpt = ` -subj "${subject.toString()}" `;
|
|
951
|
-
|
|
953
|
+
const caCommonName = subject.commonName || "NodeOPCUA-CA";
|
|
954
|
+
setEnv("ALTNAME", `URI:urn:${caCommonName}`);
|
|
952
955
|
const options = { cwd: caRootDir };
|
|
953
956
|
const configFile = generateStaticConfig("conf/caconfig.cnf", options);
|
|
954
957
|
const configOption = ` -config ${q3(n4(configFile))}`;
|
|
@@ -2050,6 +2053,14 @@ var CertificateManagerState = /* @__PURE__ */ ((CertificateManagerState2) => {
|
|
|
2050
2053
|
CertificateManagerState2[CertificateManagerState2["Disposed"] = 4] = "Disposed";
|
|
2051
2054
|
return CertificateManagerState2;
|
|
2052
2055
|
})(CertificateManagerState || {});
|
|
2056
|
+
var ChainCompletionStatus = /* @__PURE__ */ ((ChainCompletionStatus2) => {
|
|
2057
|
+
ChainCompletionStatus2["AlreadyComplete"] = "AlreadyComplete";
|
|
2058
|
+
ChainCompletionStatus2["ChainCompleted"] = "ChainCompleted";
|
|
2059
|
+
ChainCompletionStatus2["IssuerNotFound"] = "IssuerNotFound";
|
|
2060
|
+
ChainCompletionStatus2["EmptyChain"] = "EmptyChain";
|
|
2061
|
+
ChainCompletionStatus2["MaxDepthReached"] = "MaxDepthReached";
|
|
2062
|
+
return ChainCompletionStatus2;
|
|
2063
|
+
})(ChainCompletionStatus || {});
|
|
2053
2064
|
var CertificateManager = class _CertificateManager extends import_node_events.EventEmitter {
|
|
2054
2065
|
// ── Global instance registry ─────────────────────────────────
|
|
2055
2066
|
// Tracks all initialized CertificateManager instances so their
|
|
@@ -2142,6 +2153,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
2142
2153
|
#filenameToHash = /* @__PURE__ */ new Map();
|
|
2143
2154
|
#initializingPromise;
|
|
2144
2155
|
#addCertValidation;
|
|
2156
|
+
#disableFileWatchers;
|
|
2145
2157
|
#thumbs = {
|
|
2146
2158
|
rejected: /* @__PURE__ */ new Map(),
|
|
2147
2159
|
trusted: /* @__PURE__ */ new Map(),
|
|
@@ -2175,6 +2187,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
2175
2187
|
ignoreMissingRevocationList: v.ignoreMissingRevocationList ?? false,
|
|
2176
2188
|
maxChainLength: v.maxChainLength ?? 5
|
|
2177
2189
|
};
|
|
2190
|
+
this.#disableFileWatchers = options.disableFileWatchers ?? process.env.OPCUA_PKI_DISABLE_FILE_WATCHERS === "true";
|
|
2178
2191
|
mkdirRecursiveSync(options.location);
|
|
2179
2192
|
if (!import_node_fs10.default.existsSync(this.#location)) {
|
|
2180
2193
|
throw new Error(`CertificateManager cannot access location ${this.#location}`);
|
|
@@ -3039,6 +3052,75 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
3039
3052
|
}
|
|
3040
3053
|
return selectedTrustedCertificates.length > 0 ? selectedTrustedCertificates[0].certificate : null;
|
|
3041
3054
|
}
|
|
3055
|
+
/**
|
|
3056
|
+
* Outcome status for {@link CertificateManager.completeCertificateChain}.
|
|
3057
|
+
*/
|
|
3058
|
+
static ChainCompletionStatus = ChainCompletionStatus;
|
|
3059
|
+
/**
|
|
3060
|
+
* Complete a certificate chain by walking the issuer store.
|
|
3061
|
+
*
|
|
3062
|
+
* Starting from the last certificate in the provided chain, this method
|
|
3063
|
+
* repeatedly calls {@link findIssuerCertificate} to locate the parent
|
|
3064
|
+
* certificate until it reaches a self-signed root or can no longer find
|
|
3065
|
+
* an issuer.
|
|
3066
|
+
*
|
|
3067
|
+
* @param chain - the (potentially partial) certificate chain, leaf first
|
|
3068
|
+
* @param maxDepth - maximum number of issuers to append (default: 10)
|
|
3069
|
+
* @returns a {@link ChainCompletionResult} containing the (possibly completed)
|
|
3070
|
+
* chain, a status code, and an optional diagnostic message.
|
|
3071
|
+
*/
|
|
3072
|
+
async completeCertificateChain(chain, maxDepth = 10) {
|
|
3073
|
+
if (chain.length === 0) {
|
|
3074
|
+
return {
|
|
3075
|
+
chain,
|
|
3076
|
+
status: "EmptyChain" /* EmptyChain */,
|
|
3077
|
+
message: "Input chain is empty \u2014 nothing to complete."
|
|
3078
|
+
};
|
|
3079
|
+
}
|
|
3080
|
+
await this.#scanCertFolder(this.issuersCertFolder, this.#thumbs.issuers.certs);
|
|
3081
|
+
const result = [...chain];
|
|
3082
|
+
let depth = 0;
|
|
3083
|
+
while (depth < maxDepth) {
|
|
3084
|
+
const lastCert = result[result.length - 1];
|
|
3085
|
+
const lastInfo = (0, import_node_opcua_crypto5.exploreCertificate)(lastCert);
|
|
3086
|
+
if (isSelfSigned2(lastInfo)) {
|
|
3087
|
+
const wasExtended = result.length > chain.length;
|
|
3088
|
+
return {
|
|
3089
|
+
chain: result,
|
|
3090
|
+
status: wasExtended ? "ChainCompleted" /* ChainCompleted */ : "AlreadyComplete" /* AlreadyComplete */,
|
|
3091
|
+
message: wasExtended ? `Chain completed: ${result.length - chain.length} issuer(s) appended, ending at self-signed root "${lastInfo.tbsCertificate.subject.commonName}".` : `Chain is already complete (self-signed root "${lastInfo.tbsCertificate.subject.commonName}").`
|
|
3092
|
+
};
|
|
3093
|
+
}
|
|
3094
|
+
const issuerCert = await this.findIssuerCertificate(lastCert);
|
|
3095
|
+
if (!issuerCert) {
|
|
3096
|
+
const cn = lastInfo.tbsCertificate.subject.commonName ?? "?";
|
|
3097
|
+
const akid = lastInfo.tbsCertificate.extensions?.authorityKeyIdentifier?.keyIdentifier ?? "?";
|
|
3098
|
+
const msg = `Cannot find issuer for "${cn}" (authorityKeyIdentifier: ${akid}). Ensure the CA certificate is present in the issuers/certs folder.`;
|
|
3099
|
+
warningLog(`completeCertificateChain: ${msg}`);
|
|
3100
|
+
return {
|
|
3101
|
+
chain: result,
|
|
3102
|
+
status: "IssuerNotFound" /* IssuerNotFound */,
|
|
3103
|
+
message: msg
|
|
3104
|
+
};
|
|
3105
|
+
}
|
|
3106
|
+
const issuerFingerprint = makeFingerprint(issuerCert);
|
|
3107
|
+
const alreadyInChain = result.some((c) => makeFingerprint(c) === issuerFingerprint);
|
|
3108
|
+
if (alreadyInChain) {
|
|
3109
|
+
return {
|
|
3110
|
+
chain: result,
|
|
3111
|
+
status: "AlreadyComplete" /* AlreadyComplete */,
|
|
3112
|
+
message: `Chain ends at root "${(0, import_node_opcua_crypto5.exploreCertificate)(issuerCert).tbsCertificate.subject.commonName}" (already present in chain).`
|
|
3113
|
+
};
|
|
3114
|
+
}
|
|
3115
|
+
result.push(issuerCert);
|
|
3116
|
+
depth++;
|
|
3117
|
+
}
|
|
3118
|
+
return {
|
|
3119
|
+
chain: result,
|
|
3120
|
+
status: "MaxDepthReached" /* MaxDepthReached */,
|
|
3121
|
+
message: `Chain completion stopped after ${maxDepth} iterations \u2014 possible circular chain or very deep hierarchy.`
|
|
3122
|
+
};
|
|
3123
|
+
}
|
|
3042
3124
|
/**
|
|
3043
3125
|
*
|
|
3044
3126
|
* check if the certificate explicitly appear in the trust list, the reject list or none.
|
|
@@ -3234,11 +3316,15 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
3234
3316
|
this.#scanCrlFolder(this.crlFolder, this.#thumbs.crl),
|
|
3235
3317
|
this.#scanCrlFolder(this.issuersCrlFolder, this.#thumbs.issuersCrl)
|
|
3236
3318
|
]);
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3319
|
+
if (this.#disableFileWatchers) {
|
|
3320
|
+
import_node_fs10.default.watch = origWatch;
|
|
3321
|
+
} else {
|
|
3322
|
+
this.#startWatcher(this.trustedFolder, this.#thumbs.trusted, createUnreffedWatcher, "trusted");
|
|
3323
|
+
this.#startWatcher(this.issuersCertFolder, this.#thumbs.issuers.certs, createUnreffedWatcher, "issuersCerts");
|
|
3324
|
+
this.#startWatcher(this.rejectedFolder, this.#thumbs.rejected, createUnreffedWatcher, "rejected");
|
|
3325
|
+
this.#startCrlWatcher(this.crlFolder, this.#thumbs.crl, createUnreffedWatcher, "crl");
|
|
3326
|
+
this.#startCrlWatcher(this.issuersCrlFolder, this.#thumbs.issuersCrl, createUnreffedWatcher, "issuersCrl");
|
|
3327
|
+
}
|
|
3242
3328
|
}
|
|
3243
3329
|
/**
|
|
3244
3330
|
* Scan a certificate folder and populate the in-memory index.
|
|
@@ -3420,6 +3506,7 @@ var CertificateManager = class _CertificateManager extends import_node_events.Ev
|
|
|
3420
3506
|
CertificateAuthority,
|
|
3421
3507
|
CertificateManager,
|
|
3422
3508
|
CertificateManagerState,
|
|
3509
|
+
ChainCompletionStatus,
|
|
3423
3510
|
Subject,
|
|
3424
3511
|
VerificationStatus,
|
|
3425
3512
|
adjustApplicationUri,
|