node-opcua-server-configuration 2.163.1 → 2.165.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/clientTools/certificate_types.d.ts +15 -0
- package/dist/clientTools/certificate_types.js +19 -0
- package/dist/clientTools/certificate_types.js.map +1 -0
- package/dist/clientTools/get_certificate_key_type.d.ts +6 -0
- package/dist/clientTools/get_certificate_key_type.js +55 -0
- package/dist/clientTools/get_certificate_key_type.js.map +1 -0
- package/dist/clientTools/index.d.ts +2 -1
- package/dist/clientTools/index.js +2 -17
- package/dist/clientTools/index.js.map +1 -1
- package/dist/clientTools/push_certificate_management_client.d.ts +10 -10
- package/dist/clientTools/push_certificate_management_client.js +85 -89
- package/dist/clientTools/push_certificate_management_client.js.map +1 -1
- package/dist/index.d.ts +9 -7
- package/dist/index.js +9 -23
- package/dist/index.js.map +1 -1
- package/dist/push_certificate_manager.d.ts +6 -5
- package/dist/push_certificate_manager.js +1 -2
- package/dist/server/certificate_validation.d.ts +15 -0
- package/dist/server/certificate_validation.js +76 -0
- package/dist/server/certificate_validation.js.map +1 -0
- package/dist/server/file_transaction_manager.d.ts +30 -0
- package/dist/server/file_transaction_manager.js +223 -0
- package/dist/server/file_transaction_manager.js.map +1 -0
- package/dist/server/install_certificate_file_watcher.d.ts +1 -1
- package/dist/server/install_certificate_file_watcher.js +8 -14
- package/dist/server/install_certificate_file_watcher.js.map +1 -1
- package/dist/server/install_push_certitifate_management.d.ts +6 -6
- package/dist/server/install_push_certitifate_management.js +59 -81
- package/dist/server/install_push_certitifate_management.js.map +1 -1
- package/dist/server/promote_trust_list.d.ts +1 -1
- package/dist/server/promote_trust_list.js +348 -82
- package/dist/server/promote_trust_list.js.map +1 -1
- package/dist/server/push_certificate_manager/apply_changes.d.ts +4 -0
- package/dist/server/push_certificate_manager/apply_changes.js +65 -0
- package/dist/server/push_certificate_manager/apply_changes.js.map +1 -0
- package/dist/server/push_certificate_manager/create_signing_request.d.ts +5 -0
- package/dist/server/push_certificate_manager/create_signing_request.js +108 -0
- package/dist/server/push_certificate_manager/create_signing_request.js.map +1 -0
- package/dist/server/push_certificate_manager/get_rejected_list.d.ts +3 -0
- package/dist/server/push_certificate_manager/get_rejected_list.js +46 -0
- package/dist/server/push_certificate_manager/get_rejected_list.js.map +1 -0
- package/dist/server/push_certificate_manager/internal_context.d.ts +35 -0
- package/dist/server/push_certificate_manager/internal_context.js +45 -0
- package/dist/server/push_certificate_manager/internal_context.js.map +1 -0
- package/dist/server/push_certificate_manager/subject_to_string.d.ts +3 -0
- package/dist/server/push_certificate_manager/subject_to_string.js +27 -0
- package/dist/server/push_certificate_manager/subject_to_string.js.map +1 -0
- package/dist/server/push_certificate_manager/update_certificate.d.ts +5 -0
- package/dist/server/push_certificate_manager/update_certificate.js +134 -0
- package/dist/server/push_certificate_manager/update_certificate.js.map +1 -0
- package/dist/server/push_certificate_manager/util.d.ts +29 -0
- package/dist/server/push_certificate_manager/util.js +117 -0
- package/dist/server/push_certificate_manager/util.js.map +1 -0
- package/dist/server/push_certificate_manager_helpers.d.ts +5 -2
- package/dist/server/push_certificate_manager_helpers.js +110 -113
- package/dist/server/push_certificate_manager_helpers.js.map +1 -1
- package/dist/server/push_certificate_manager_server_impl.d.ts +37 -30
- package/dist/server/push_certificate_manager_server_impl.js +58 -438
- package/dist/server/push_certificate_manager_server_impl.js.map +1 -1
- package/dist/server/roles_and_permissions.d.ts +1 -1
- package/dist/server/roles_and_permissions.js +24 -27
- package/dist/server/roles_and_permissions.js.map +1 -1
- package/dist/server/tools.d.ts +1 -1
- package/dist/server/tools.js +7 -13
- package/dist/server/tools.js.map +1 -1
- package/dist/server/trust_list_server.d.ts +2 -2
- package/dist/server/trust_list_server.js +40 -29
- package/dist/server/trust_list_server.js.map +1 -1
- package/dist/standard_certificate_types.js +6 -9
- package/dist/standard_certificate_types.js.map +1 -1
- package/dist/trust_list.d.ts +2 -2
- package/dist/trust_list.js +1 -2
- package/dist/trust_list_impl.js +1 -2
- package/dist/trust_list_impl.js.map +1 -1
- package/package.json +30 -30
- package/source/clientTools/certificate_types.ts +21 -0
- package/source/clientTools/get_certificate_key_type.ts +73 -0
- package/source/clientTools/index.ts +2 -1
- package/source/clientTools/push_certificate_management_client.ts +49 -44
- package/source/index.ts +9 -7
- package/source/push_certificate_manager.ts +17 -18
- package/source/server/certificate_validation.ts +103 -0
- package/source/server/file_transaction_manager.ts +253 -0
- package/source/server/install_certificate_file_watcher.ts +15 -11
- package/source/server/install_push_certitifate_management.ts +52 -68
- package/source/server/promote_trust_list.ts +392 -73
- package/source/server/push_certificate_manager/apply_changes.ts +73 -0
- package/source/server/push_certificate_manager/create_signing_request.ts +137 -0
- package/source/server/push_certificate_manager/get_rejected_list.ts +63 -0
- package/source/server/push_certificate_manager/internal_context.ts +63 -0
- package/source/server/push_certificate_manager/subject_to_string.ts +25 -0
- package/source/server/push_certificate_manager/update_certificate.ts +203 -0
- package/source/server/push_certificate_manager/util.ts +145 -0
- package/source/server/push_certificate_manager_helpers.ts +62 -52
- package/source/server/push_certificate_manager_server_impl.ts +133 -552
- package/source/server/roles_and_permissions.ts +7 -8
- package/source/server/tools.ts +2 -5
- package/source/server/trust_list_server.ts +24 -9
- package/source/standard_certificate_types.ts +2 -3
- package/source/trust_list.ts +26 -33
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module node-opcua-server-configuration.client
|
|
3
3
|
*/
|
|
4
|
-
import { ByteString } from "node-opcua-basic-types";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { DataType, VariantArrayType, VariantLike } from "node-opcua-variant";
|
|
4
|
+
import type { ByteString } from "node-opcua-basic-types";
|
|
5
|
+
import { BinaryStream } from "node-opcua-binary-stream";
|
|
6
|
+
import type { Certificate } from "node-opcua-crypto/web";
|
|
7
|
+
import { AttributeIds, coerceQualifiedName, type QualifiedNameLike } from "node-opcua-data-model";
|
|
9
8
|
import { ClientFile, OpenFileMode } from "node-opcua-file-transfer";
|
|
10
|
-
import {
|
|
9
|
+
import { NodeId, resolveNodeId } from "node-opcua-nodeid";
|
|
10
|
+
import type { CallMethodRequestLike, IBasicSessionAsync } from "node-opcua-pseudo-session";
|
|
11
11
|
import { makeBrowsePath } from "node-opcua-service-translate-browse-path";
|
|
12
|
-
import {
|
|
12
|
+
import { type StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
13
13
|
import { TrustListDataType } from "node-opcua-types";
|
|
14
|
-
import {
|
|
14
|
+
import { DataType, VariantArrayType, type VariantLike } from "node-opcua-variant";
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import type {
|
|
17
17
|
CreateSigningRequestResult,
|
|
18
18
|
GetRejectedListResult,
|
|
19
19
|
PushCertificateManager,
|
|
20
20
|
UpdateCertificateResult
|
|
21
|
-
} from "../push_certificate_manager";
|
|
22
|
-
|
|
23
|
-
import { ITrustList } from "../trust_list";
|
|
24
|
-
import { TrustListMasks } from "../server/trust_list_server";
|
|
21
|
+
} from "../push_certificate_manager.js";
|
|
22
|
+
import type { TrustListMasks } from "../server/trust_list_server.js";
|
|
23
|
+
import type { ITrustList } from "../trust_list.js";
|
|
25
24
|
|
|
26
25
|
const serverConfigurationNodeId = resolveNodeId("ServerConfiguration");
|
|
27
26
|
const createSigningRequestMethod = resolveNodeId("ServerConfiguration_CreateSigningRequest");
|
|
@@ -34,7 +33,6 @@ const defaultApplicationGroup = resolveNodeId("ServerConfiguration_CertificateGr
|
|
|
34
33
|
const defaultHttpsGroup = resolveNodeId("ServerConfiguration_CertificateGroups_DefaultHttpsGroup");
|
|
35
34
|
const defaultUserTokenGroup = resolveNodeId("ServerConfiguration_CertificateGroups_DefaultUserTokenGroup");
|
|
36
35
|
|
|
37
|
-
|
|
38
36
|
function findCertificateGroupNodeId(certificateGroup: NodeId | string): NodeId {
|
|
39
37
|
if (certificateGroup instanceof NodeId) {
|
|
40
38
|
return certificateGroup;
|
|
@@ -64,7 +62,10 @@ export class TrustListClient extends ClientFile implements ITrustList {
|
|
|
64
62
|
private removeCertificateNodeId?: NodeId;
|
|
65
63
|
private openWithMasksNodeId?: NodeId;
|
|
66
64
|
|
|
67
|
-
constructor(
|
|
65
|
+
constructor(
|
|
66
|
+
session: IBasicSessionAsync,
|
|
67
|
+
public nodeId: NodeId
|
|
68
|
+
) {
|
|
68
69
|
super(session, nodeId);
|
|
69
70
|
}
|
|
70
71
|
/**
|
|
@@ -78,12 +79,12 @@ export class TrustListClient extends ClientFile implements ITrustList {
|
|
|
78
79
|
makeBrowsePath(this.nodeId, "/OpenWithMasks") // OpenWithMasks Mandatory
|
|
79
80
|
]);
|
|
80
81
|
|
|
81
|
-
this.closeAndUpdateNodeId = browseResults[0].targets
|
|
82
|
-
this.addCertificateNodeId = browseResults[1].targets
|
|
83
|
-
this.removeCertificateNodeId = browseResults[2].targets
|
|
84
|
-
this.openWithMasksNodeId = browseResults[3].targets
|
|
82
|
+
this.closeAndUpdateNodeId = browseResults[0].targets?.[0].targetId;
|
|
83
|
+
this.addCertificateNodeId = browseResults[1].targets?.[0].targetId;
|
|
84
|
+
this.removeCertificateNodeId = browseResults[2].targets?.[0].targetId;
|
|
85
|
+
this.openWithMasksNodeId = browseResults[3].targets?.[0].targetId;
|
|
85
86
|
|
|
86
|
-
//
|
|
87
|
+
// c8 ignore next
|
|
87
88
|
if (!this.openWithMasksNodeId || this.openWithMasksNodeId.isEmpty()) {
|
|
88
89
|
throw new Error("Cannot find mandatory method OpenWithMask on object");
|
|
89
90
|
}
|
|
@@ -95,12 +96,12 @@ export class TrustListClient extends ClientFile implements ITrustList {
|
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
async openWithMasks(trustListMask: TrustListMasks): Promise<number> {
|
|
98
|
-
//
|
|
99
|
+
// c8 ignore next
|
|
99
100
|
if (this.fileHandle) {
|
|
100
101
|
throw new Error("File has already be opened");
|
|
101
102
|
}
|
|
102
103
|
await this.ensureInitialized();
|
|
103
|
-
//
|
|
104
|
+
// c8 ignore next
|
|
104
105
|
if (!this.openWithMasksNodeId) {
|
|
105
106
|
throw new Error("OpenWithMasks doesn't exist");
|
|
106
107
|
}
|
|
@@ -114,11 +115,11 @@ export class TrustListClient extends ClientFile implements ITrustList {
|
|
|
114
115
|
if (callMethodResult.statusCode.isNotGood()) {
|
|
115
116
|
throw new Error(callMethodResult.statusCode.name);
|
|
116
117
|
}
|
|
117
|
-
this.fileHandle = callMethodResult.outputArguments
|
|
118
|
+
this.fileHandle = callMethodResult.outputArguments?.[0].value as number;
|
|
118
119
|
return this.fileHandle;
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
async closeAndUpdate(
|
|
122
|
+
async closeAndUpdate(): Promise<boolean> {
|
|
122
123
|
if (!this.fileHandle) {
|
|
123
124
|
throw new Error("File has node been opened yet");
|
|
124
125
|
}
|
|
@@ -126,10 +127,7 @@ export class TrustListClient extends ClientFile implements ITrustList {
|
|
|
126
127
|
if (!this.closeAndUpdateNodeId) {
|
|
127
128
|
throw new Error("CloseAndUpdateMethod doesn't exist");
|
|
128
129
|
}
|
|
129
|
-
const inputArguments = [
|
|
130
|
-
{ dataType: DataType.UInt32, value: this.fileHandle },
|
|
131
|
-
{ dataType: DataType.Boolean, value: !!applyChangesRequired }
|
|
132
|
-
];
|
|
130
|
+
const inputArguments = [{ dataType: DataType.UInt32, value: this.fileHandle }];
|
|
133
131
|
const methodToCall: CallMethodRequestLike = {
|
|
134
132
|
inputArguments,
|
|
135
133
|
methodId: this.closeAndUpdateNodeId,
|
|
@@ -139,7 +137,8 @@ export class TrustListClient extends ClientFile implements ITrustList {
|
|
|
139
137
|
if (callMethodResult.statusCode.isNotGood()) {
|
|
140
138
|
throw new Error(callMethodResult.statusCode.name);
|
|
141
139
|
}
|
|
142
|
-
|
|
140
|
+
this.fileHandle = 0;
|
|
141
|
+
return callMethodResult.outputArguments?.[0].value as boolean;
|
|
143
142
|
}
|
|
144
143
|
|
|
145
144
|
async addCertificate(certificate: Certificate, isTrustedCertificate: boolean): Promise<StatusCode> {
|
|
@@ -200,21 +199,25 @@ export class TrustListClient extends ClientFile implements ITrustList {
|
|
|
200
199
|
}
|
|
201
200
|
|
|
202
201
|
async writeTrustedCertificateList(trustedList: TrustListDataType): Promise<boolean> {
|
|
203
|
-
await this.open(OpenFileMode.
|
|
202
|
+
await this.open(OpenFileMode.WriteEraseExisting);
|
|
204
203
|
const s = trustedList.binaryStoreSize();
|
|
205
204
|
const stream = new BinaryStream(s);
|
|
206
205
|
trustedList.encode(stream);
|
|
207
|
-
|
|
206
|
+
await this.write(stream.buffer);
|
|
207
|
+
return await this.closeAndUpdate();
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
export class CertificateGroup {
|
|
211
|
-
constructor(
|
|
211
|
+
constructor(
|
|
212
|
+
public session: IBasicSessionAsync,
|
|
213
|
+
public nodeId: NodeId
|
|
214
|
+
) {}
|
|
212
215
|
async getCertificateTypes(): Promise<NodeId[]> {
|
|
213
216
|
const browsePathResult = await this.session.translateBrowsePath(makeBrowsePath(this.nodeId, "/CertificateTypes"));
|
|
214
217
|
if (browsePathResult.statusCode.isNotGood()) {
|
|
215
218
|
throw new Error(browsePathResult.statusCode.name);
|
|
216
219
|
}
|
|
217
|
-
const certificateTypesNodeId = browsePathResult.targets
|
|
220
|
+
const certificateTypesNodeId = browsePathResult.targets?.[0].targetId;
|
|
218
221
|
const dataValue = await this.session.read({ nodeId: certificateTypesNodeId, attributeId: AttributeIds.Value });
|
|
219
222
|
if (dataValue.statusCode.isNotGood()) {
|
|
220
223
|
throw new Error(browsePathResult.statusCode.name);
|
|
@@ -226,7 +229,10 @@ export class CertificateGroup {
|
|
|
226
229
|
if (browsePathResult.statusCode.isNotGood()) {
|
|
227
230
|
throw new Error(browsePathResult.statusCode.name);
|
|
228
231
|
}
|
|
229
|
-
const trustListNodeId = browsePathResult.targets
|
|
232
|
+
const trustListNodeId = browsePathResult.targets?.[0].targetId;
|
|
233
|
+
if (!trustListNodeId) {
|
|
234
|
+
throw new Error("TrustList node not found");
|
|
235
|
+
}
|
|
230
236
|
return new TrustListClient(this.session, trustListNodeId);
|
|
231
237
|
}
|
|
232
238
|
}
|
|
@@ -302,7 +308,7 @@ export class ClientPushCertificateManagement implements PushCertificateManager {
|
|
|
302
308
|
|
|
303
309
|
if (callMethodResult.statusCode.isGood()) {
|
|
304
310
|
return {
|
|
305
|
-
certificateSigningRequest: callMethodResult.outputArguments
|
|
311
|
+
certificateSigningRequest: callMethodResult.outputArguments?.[0].value,
|
|
306
312
|
statusCode: callMethodResult.statusCode
|
|
307
313
|
};
|
|
308
314
|
} else {
|
|
@@ -330,11 +336,11 @@ export class ClientPushCertificateManagement implements PushCertificateManager {
|
|
|
330
336
|
};
|
|
331
337
|
const callMethodResult = await this.session.call(methodToCall);
|
|
332
338
|
if (callMethodResult.statusCode.isGood()) {
|
|
333
|
-
if (callMethodResult.outputArguments
|
|
339
|
+
if (callMethodResult.outputArguments?.[0].dataType !== DataType.ByteString) {
|
|
334
340
|
return { statusCode: StatusCodes.BadInvalidArgument };
|
|
335
341
|
}
|
|
336
342
|
return {
|
|
337
|
-
certificates: callMethodResult.outputArguments
|
|
343
|
+
certificates: callMethodResult.outputArguments?.[0].value,
|
|
338
344
|
statusCode: callMethodResult.statusCode
|
|
339
345
|
};
|
|
340
346
|
} else {
|
|
@@ -422,22 +428,21 @@ export class ClientPushCertificateManagement implements PushCertificateManager {
|
|
|
422
428
|
};
|
|
423
429
|
const callMethodResult = await this.session.call(methodToCall);
|
|
424
430
|
if (callMethodResult.statusCode.isGood()) {
|
|
425
|
-
if (!callMethodResult.outputArguments || callMethodResult.outputArguments
|
|
431
|
+
if (!callMethodResult.outputArguments || callMethodResult.outputArguments.length !== 1) {
|
|
426
432
|
return {
|
|
427
433
|
statusCode: StatusCodes.BadInternalError,
|
|
428
|
-
applyChangesRequired: false
|
|
434
|
+
applyChangesRequired: false
|
|
429
435
|
};
|
|
430
436
|
// throw Error("Internal Error, expecting 1 output result");
|
|
431
437
|
}
|
|
432
438
|
return {
|
|
433
|
-
applyChangesRequired: !!callMethodResult.outputArguments
|
|
439
|
+
applyChangesRequired: !!callMethodResult.outputArguments?.[0].value,
|
|
434
440
|
statusCode: callMethodResult.statusCode
|
|
435
441
|
};
|
|
436
442
|
} else {
|
|
437
|
-
return {
|
|
443
|
+
return {
|
|
438
444
|
statusCode: callMethodResult.statusCode,
|
|
439
445
|
applyChangesRequired: false
|
|
440
|
-
|
|
441
446
|
};
|
|
442
447
|
}
|
|
443
448
|
}
|
|
@@ -471,7 +476,7 @@ export class ClientPushCertificateManagement implements PushCertificateManager {
|
|
|
471
476
|
};
|
|
472
477
|
const callMethodResult = await this.session.call(methodToCall);
|
|
473
478
|
|
|
474
|
-
if (callMethodResult.outputArguments
|
|
479
|
+
if (callMethodResult.outputArguments?.length) {
|
|
475
480
|
throw new Error("Invalid output arguments");
|
|
476
481
|
}
|
|
477
482
|
return callMethodResult.statusCode;
|
|
@@ -507,7 +512,7 @@ export class ClientPushCertificateManagement implements PushCertificateManager {
|
|
|
507
512
|
if (browseName.toString() === "DefaultUserTokenGroup") {
|
|
508
513
|
return new CertificateGroup(this.session, defaultUserTokenGroup);
|
|
509
514
|
}
|
|
510
|
-
//
|
|
515
|
+
// c8 ignore next
|
|
511
516
|
throw new Error("Not Implemented yet");
|
|
512
517
|
}
|
|
513
518
|
public async getApplicationGroup(): Promise<CertificateGroup> {
|
package/source/index.ts
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
* @module node-opcua-server-configuration
|
|
3
3
|
*/
|
|
4
4
|
// export * from "./trust_list_impl";
|
|
5
|
-
export * from "./push_certificate_manager";
|
|
6
|
-
export * from "./clientTools/push_certificate_management_client";
|
|
7
|
-
export * from "./standard_certificate_types";
|
|
8
5
|
|
|
9
|
-
export * from "./
|
|
10
|
-
export * from "./
|
|
11
|
-
export * from "./
|
|
12
|
-
export * from "./server/
|
|
6
|
+
export * from "./clientTools/certificate_types.js";
|
|
7
|
+
export * from "./clientTools/push_certificate_management_client.js";
|
|
8
|
+
export * from "./push_certificate_manager.js";
|
|
9
|
+
export * from "./server/install_push_certitifate_management.js";
|
|
10
|
+
export * from "./server/promote_trust_list.js";
|
|
11
|
+
export * from "./server/push_certificate_manager/subject_to_string.js";
|
|
12
|
+
export * from "./server/push_certificate_manager_helpers.js";
|
|
13
|
+
export * from "./server/push_certificate_manager_server_impl.js";
|
|
14
|
+
export * from "./standard_certificate_types.js";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module node-opcua-server-configuration
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import type { ISessionContext } from "node-opcua-address-space-base";
|
|
5
|
+
import type { ByteString, UAString } from "node-opcua-basic-types";
|
|
6
|
+
import type { NodeId } from "node-opcua-nodeid";
|
|
7
|
+
import type { StatusCode } from "node-opcua-status-code";
|
|
7
8
|
|
|
8
9
|
export interface CreateSigningRequestResult {
|
|
9
10
|
statusCode: StatusCode;
|
|
@@ -21,7 +22,6 @@ export interface UpdateCertificateResult {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export interface PushCertificateManager {
|
|
24
|
-
|
|
25
25
|
/**
|
|
26
26
|
* The SupportedPrivateKeyFormats specifies the private key formats supported by the Server.
|
|
27
27
|
* Possible values include “PEM” (see RFC 5958) or “PFX” (see PKCS #12). The array is empty
|
|
@@ -65,12 +65,12 @@ export interface PushCertificateManager {
|
|
|
65
65
|
*
|
|
66
66
|
*/
|
|
67
67
|
updateCertificate(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
certificateGroupId: NodeId | string,
|
|
69
|
+
certificateTypeId: NodeId | string,
|
|
70
|
+
certificate: ByteString,
|
|
71
|
+
issuerCertificates: ByteString[],
|
|
72
|
+
privateKeyFormat?: UAString,
|
|
73
|
+
privateKey?: ByteString
|
|
74
74
|
): Promise<UpdateCertificateResult>;
|
|
75
75
|
|
|
76
76
|
/**
|
|
@@ -102,7 +102,7 @@ export interface PushCertificateManager {
|
|
|
102
102
|
* Result Code Description
|
|
103
103
|
* Bad_UserAccessDenied The current user does not have the rights required.
|
|
104
104
|
*/
|
|
105
|
-
applyChanges(): Promise<StatusCode>;
|
|
105
|
+
applyChanges(context?: ISessionContext): Promise<StatusCode>;
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
108
|
* The CreateSigningRequest Method asks the Server to create a PKCS #10 encoded Certificate
|
|
@@ -136,11 +136,11 @@ export interface PushCertificateManager {
|
|
|
136
136
|
* Bad_UserAccessDenied The current user does not have the rights required.
|
|
137
137
|
*/
|
|
138
138
|
createSigningRequest(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
certificateGroupId: NodeId | string,
|
|
140
|
+
certificateTypeId: NodeId | string,
|
|
141
|
+
subjectName: string | null,
|
|
142
|
+
regeneratePrivateKey?: boolean,
|
|
143
|
+
nonce?: ByteString
|
|
144
144
|
): Promise<CreateSigningRequestResult>;
|
|
145
145
|
|
|
146
146
|
/**
|
|
@@ -159,6 +159,5 @@ export interface PushCertificateManager {
|
|
|
159
159
|
* Bad_UserAccessDenied The current user does not have the rights required
|
|
160
160
|
*/
|
|
161
161
|
|
|
162
|
-
getRejectedList(): Promise</*certificates*/GetRejectedListResult>;
|
|
163
|
-
|
|
162
|
+
getRejectedList(): Promise</*certificates*/ GetRejectedListResult>;
|
|
164
163
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node-opcua-server-configuration-server
|
|
3
|
+
*/
|
|
4
|
+
import type { ByteString } from "node-opcua-basic-types";
|
|
5
|
+
import type { OPCUACertificateManager } from "node-opcua-certificate-manager";
|
|
6
|
+
import { type CertificateInternals, exploreCertificate, verifyCertificateChain } from "node-opcua-crypto/web";
|
|
7
|
+
import { make_errorLog, make_warningLog } from "node-opcua-debug";
|
|
8
|
+
import { type StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
9
|
+
|
|
10
|
+
const warningLog = make_warningLog("ServerConfiguration");
|
|
11
|
+
const errorLog = make_errorLog("ServerConfiguration");
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Validates the certificate and its issuer chain, including parsing, date validity,
|
|
15
|
+
* chain verification, and trust verification.
|
|
16
|
+
* @returns Object with statusCode. If Good, also contains the concatenated certificateChain.
|
|
17
|
+
*/
|
|
18
|
+
export async function validateCertificateAndChain(
|
|
19
|
+
certificateManager: OPCUACertificateManager,
|
|
20
|
+
isApplicationGroup: boolean,
|
|
21
|
+
certificate: Buffer,
|
|
22
|
+
issuerCertificates: ByteString[] | null | undefined
|
|
23
|
+
): Promise<{ statusCode: StatusCode; certificateChain?: Buffer }> {
|
|
24
|
+
let certInfo: CertificateInternals;
|
|
25
|
+
try {
|
|
26
|
+
certInfo = exploreCertificate(certificate);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
errorLog("Cannot parse certificate:", (err as Error).message);
|
|
29
|
+
return { statusCode: StatusCodes.BadCertificateInvalid };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const issuerCertBuffers = (issuerCertificates || []).filter((cert): cert is Buffer => {
|
|
33
|
+
return Buffer.isBuffer(cert) && cert.length > 0;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
if ((issuerCertificates || []).length !== issuerCertBuffers.length) {
|
|
37
|
+
warningLog("issuerCertificates contains invalid entries");
|
|
38
|
+
return { statusCode: StatusCodes.BadCertificateInvalid };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const issuerCert of issuerCertBuffers) {
|
|
42
|
+
try {
|
|
43
|
+
const issuerInfo = exploreCertificate(issuerCert);
|
|
44
|
+
const nowIssuer = new Date();
|
|
45
|
+
if (issuerInfo.tbsCertificate.validity.notBefore.getTime() > nowIssuer.getTime()) {
|
|
46
|
+
warningLog("Issuer certificate is not yet valid");
|
|
47
|
+
return { statusCode: StatusCodes.BadSecurityChecksFailed };
|
|
48
|
+
}
|
|
49
|
+
if (issuerInfo.tbsCertificate.validity.notAfter.getTime() < nowIssuer.getTime()) {
|
|
50
|
+
warningLog("Issuer certificate is out of date");
|
|
51
|
+
return { statusCode: StatusCodes.BadSecurityChecksFailed };
|
|
52
|
+
}
|
|
53
|
+
} catch (err) {
|
|
54
|
+
errorLog("Cannot parse issuer certificate:", (err as Error).message);
|
|
55
|
+
return { statusCode: StatusCodes.BadCertificateInvalid };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (issuerCertBuffers.length > 0) {
|
|
60
|
+
const chainCheck = await verifyCertificateChain([certificate, ...issuerCertBuffers]);
|
|
61
|
+
if (chainCheck.status !== "Good") {
|
|
62
|
+
warningLog("Issuer chain validation failed:", chainCheck.status, chainCheck.reason);
|
|
63
|
+
return { statusCode: StatusCodes.BadSecurityChecksFailed };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const certificateChain = Buffer.concat([certificate, ...issuerCertBuffers]);
|
|
68
|
+
|
|
69
|
+
// Trust validation is only relevant for client certificates, not the server's own certificate
|
|
70
|
+
if (!isApplicationGroup) {
|
|
71
|
+
if (certificateManager.verifyCertificate) {
|
|
72
|
+
const status = await certificateManager.verifyCertificate(certificateChain, {
|
|
73
|
+
acceptCertificateWithValidIssuerChain: true
|
|
74
|
+
});
|
|
75
|
+
if (status !== "Good") {
|
|
76
|
+
warningLog("Certificate trust validation failed:", status);
|
|
77
|
+
return { statusCode: StatusCodes.BadSecurityChecksFailed };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const now = new Date();
|
|
83
|
+
if (certInfo.tbsCertificate.validity.notBefore.getTime() > now.getTime()) {
|
|
84
|
+
warningLog(
|
|
85
|
+
"Certificate is not yet valid : not before ",
|
|
86
|
+
certInfo.tbsCertificate.validity.notBefore.toISOString(),
|
|
87
|
+
"now = ",
|
|
88
|
+
now.toISOString()
|
|
89
|
+
);
|
|
90
|
+
return { statusCode: StatusCodes.BadSecurityChecksFailed };
|
|
91
|
+
}
|
|
92
|
+
if (certInfo.tbsCertificate.validity.notAfter.getTime() < now.getTime()) {
|
|
93
|
+
warningLog(
|
|
94
|
+
"Certificate is already out of date : not after ",
|
|
95
|
+
certInfo.tbsCertificate.validity.notAfter.toISOString(),
|
|
96
|
+
"now = ",
|
|
97
|
+
now.toISOString()
|
|
98
|
+
);
|
|
99
|
+
return { statusCode: StatusCodes.BadSecurityChecksFailed };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return { statusCode: StatusCodes.Good, certificateChain };
|
|
103
|
+
}
|