node-opcua-server 2.82.0 → 2.84.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/base_server.js +19 -0
- package/dist/base_server.js.map +1 -1
- package/dist/opcua_server.js +1 -1
- package/dist/opcua_server.js.map +1 -1
- package/dist/server_end_point.d.ts +9 -7
- package/dist/server_end_point.js +82 -61
- package/dist/server_end_point.js.map +1 -1
- package/package.json +43 -43
- package/source/base_server.ts +32 -8
- package/source/opcua_server.ts +3 -3
- package/source/server_end_point.ts +116 -79
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
import { UserTokenType } from "node-opcua-service-endpoints";
|
|
28
28
|
import { EndpointDescription } from "node-opcua-service-endpoints";
|
|
29
29
|
import { ApplicationDescription } from "node-opcua-service-endpoints";
|
|
30
|
+
import { UserTokenPolicyOptions } from "node-opcua-types";
|
|
30
31
|
import { IChannelData } from "./i_channel_data";
|
|
31
32
|
import { ISocketData } from "./i_socket_data";
|
|
32
33
|
|
|
@@ -155,26 +156,27 @@ export interface OPCUAServerEndPointOptions {
|
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
export interface EndpointDescriptionParams {
|
|
158
|
-
allowAnonymous?: boolean;
|
|
159
159
|
restricted?: boolean;
|
|
160
160
|
allowUnsecurePassword?: boolean;
|
|
161
161
|
resourcePath?: string;
|
|
162
162
|
alternateHostname?: string[];
|
|
163
163
|
hostname: string;
|
|
164
164
|
securityPolicies: SecurityPolicy[];
|
|
165
|
+
userTokenTypes: UserTokenType[];
|
|
165
166
|
}
|
|
166
167
|
|
|
167
168
|
export interface AddStandardEndpointDescriptionsParam {
|
|
168
|
-
securityModes?: MessageSecurityMode[];
|
|
169
|
-
securityPolicies?: SecurityPolicy[];
|
|
170
|
-
disableDiscovery?: boolean;
|
|
171
|
-
|
|
172
169
|
allowAnonymous?: boolean;
|
|
170
|
+
disableDiscovery?: boolean;
|
|
171
|
+
securityModes?: MessageSecurityMode[];
|
|
172
|
+
|
|
173
173
|
restricted?: boolean;
|
|
174
|
-
hostname?: string;
|
|
175
|
-
alternateHostname?: string[];
|
|
176
174
|
allowUnsecurePassword?: boolean;
|
|
177
175
|
resourcePath?: string;
|
|
176
|
+
alternateHostname?: string[];
|
|
177
|
+
hostname?: string;
|
|
178
|
+
securityPolicies?: SecurityPolicy[];
|
|
179
|
+
userTokenTypes?: UserTokenType[];
|
|
178
180
|
}
|
|
179
181
|
|
|
180
182
|
function getUniqueName(name: string, collection: { [key: string]: number }) {
|
|
@@ -367,17 +369,8 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
367
369
|
public addEndpointDescription(
|
|
368
370
|
securityMode: MessageSecurityMode,
|
|
369
371
|
securityPolicy: SecurityPolicy,
|
|
370
|
-
options
|
|
372
|
+
options: EndpointDescriptionParams
|
|
371
373
|
): void {
|
|
372
|
-
if (!options) {
|
|
373
|
-
options = {
|
|
374
|
-
hostname: getFullyQualifiedDomainName(),
|
|
375
|
-
securityPolicies: [SecurityPolicy.Basic256Sha256]
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
options.allowAnonymous = options.allowAnonymous === undefined ? true : options.allowAnonymous;
|
|
380
|
-
|
|
381
374
|
// istanbul ignore next
|
|
382
375
|
if (securityMode === MessageSecurityMode.None && securityPolicy !== SecurityPolicy.None) {
|
|
383
376
|
throw new Error(" invalid security ");
|
|
@@ -405,6 +398,8 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
405
398
|
throw new Error(" endpoint already exist");
|
|
406
399
|
}
|
|
407
400
|
|
|
401
|
+
const userTokenTypes = options.userTokenTypes;
|
|
402
|
+
|
|
408
403
|
// now build endpointUrl
|
|
409
404
|
this._endpoints.push(
|
|
410
405
|
_makeEndpointDescription({
|
|
@@ -419,12 +414,13 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
419
414
|
securityMode,
|
|
420
415
|
securityPolicy,
|
|
421
416
|
|
|
422
|
-
allowAnonymous: options.allowAnonymous,
|
|
423
417
|
allowUnsecurePassword: options.allowUnsecurePassword,
|
|
424
418
|
resourcePath: options.resourcePath,
|
|
425
419
|
|
|
426
420
|
restricted: !!options.restricted,
|
|
427
|
-
securityPolicies: options
|
|
421
|
+
securityPolicies: options.securityPolicies || [],
|
|
422
|
+
|
|
423
|
+
userTokenTypes
|
|
428
424
|
})
|
|
429
425
|
);
|
|
430
426
|
}
|
|
@@ -440,6 +436,14 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
440
436
|
|
|
441
437
|
options.securityModes = options.securityModes || defaultSecurityModes;
|
|
442
438
|
options.securityPolicies = options.securityPolicies || defaultSecurityPolicies;
|
|
439
|
+
options.userTokenTypes = options.userTokenTypes || defaultUserTokenTypes;
|
|
440
|
+
|
|
441
|
+
options.allowAnonymous = options.allowAnonymous === undefined ? true : options.allowAnonymous;
|
|
442
|
+
// make sure we do not have anonymous
|
|
443
|
+
if (!options.allowAnonymous) {
|
|
444
|
+
options.userTokenTypes = options.userTokenTypes.filter((r) => r !== UserTokenType.Anonymous);
|
|
445
|
+
}
|
|
446
|
+
|
|
443
447
|
|
|
444
448
|
const defaultHostname = options.hostname || getFullyQualifiedDomainName();
|
|
445
449
|
|
|
@@ -450,11 +454,17 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
450
454
|
options.alternateHostname = [options.alternateHostname];
|
|
451
455
|
}
|
|
452
456
|
// remove duplicates if any (uniq)
|
|
453
|
-
hostnames = [...new Set(hostnames.concat(options.alternateHostname
|
|
457
|
+
hostnames = [...new Set(hostnames.concat(options.alternateHostname))];
|
|
454
458
|
|
|
455
459
|
for (const alternateHostname of hostnames) {
|
|
456
|
-
const optionsE =
|
|
457
|
-
|
|
460
|
+
const optionsE: EndpointDescriptionParams = {
|
|
461
|
+
hostname: alternateHostname,
|
|
462
|
+
securityPolicies: options.securityPolicies,
|
|
463
|
+
userTokenTypes: options.userTokenTypes,
|
|
464
|
+
allowUnsecurePassword: options.allowUnsecurePassword,
|
|
465
|
+
alternateHostname: options.alternateHostname,
|
|
466
|
+
resourcePath: options.resourcePath
|
|
467
|
+
};
|
|
458
468
|
|
|
459
469
|
if (options.securityModes.indexOf(MessageSecurityMode.None) >= 0) {
|
|
460
470
|
this.addEndpointDescription(MessageSecurityMode.None, SecurityPolicy.None, optionsE);
|
|
@@ -966,7 +976,6 @@ interface MakeEndpointDescriptionOptions {
|
|
|
966
976
|
};
|
|
967
977
|
*/
|
|
968
978
|
resourcePath?: string;
|
|
969
|
-
allowAnonymous?: boolean; // default true
|
|
970
979
|
|
|
971
980
|
// allow un-encrypted password in userNameIdentity
|
|
972
981
|
allowUnsecurePassword?: boolean; // default false
|
|
@@ -981,6 +990,15 @@ interface MakeEndpointDescriptionOptions {
|
|
|
981
990
|
collection: { [key: string]: number };
|
|
982
991
|
|
|
983
992
|
securityPolicies: SecurityPolicy[];
|
|
993
|
+
|
|
994
|
+
userTokenTypes: UserTokenType[];
|
|
995
|
+
/**
|
|
996
|
+
*
|
|
997
|
+
* default value: false;
|
|
998
|
+
*
|
|
999
|
+
* note: setting noUserIdentityTokens=true is useful for pure local discovery servers
|
|
1000
|
+
*/
|
|
1001
|
+
noUserIdentityTokens?: boolean;
|
|
984
1002
|
}
|
|
985
1003
|
|
|
986
1004
|
interface EndpointDescriptionEx extends EndpointDescription {
|
|
@@ -1040,72 +1058,85 @@ function _makeEndpointDescription(options: MakeEndpointDescriptionOptions): Endp
|
|
|
1040
1058
|
|
|
1041
1059
|
const securityPolicyUri = toURI(options.securityPolicy);
|
|
1042
1060
|
|
|
1043
|
-
const userIdentityTokens = [];
|
|
1044
|
-
|
|
1045
|
-
if (options.securityPolicy === SecurityPolicy.None) {
|
|
1046
|
-
if (options.allowUnsecurePassword) {
|
|
1047
|
-
userIdentityTokens.push({
|
|
1048
|
-
policyId: u("username_unsecure"),
|
|
1049
|
-
tokenType: UserTokenType.UserName,
|
|
1061
|
+
const userIdentityTokens: UserTokenPolicyOptions[] = [];
|
|
1050
1062
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1063
|
+
const registerIdentity2 = (tokenType: UserTokenType, securityPolicy: SecurityPolicy, name: string) => {
|
|
1064
|
+
return registerIdentity({
|
|
1065
|
+
policyId: u(name),
|
|
1066
|
+
tokenType,
|
|
1067
|
+
issuedTokenType: null,
|
|
1068
|
+
issuerEndpointUrl: null,
|
|
1069
|
+
securityPolicyUri: securityPolicy
|
|
1070
|
+
});
|
|
1071
|
+
};
|
|
1072
|
+
const registerIdentity = (r: UserTokenPolicyOptions) => {
|
|
1073
|
+
const tokenType = r.tokenType === undefined ? UserTokenType.Invalid : r.tokenType;
|
|
1074
|
+
const securityPolicy = (r.securityPolicyUri || "") as SecurityPolicy;
|
|
1075
|
+
if (!securityPolicy && options.userTokenTypes.indexOf(tokenType) >= 0) {
|
|
1076
|
+
userIdentityTokens.push(r);
|
|
1077
|
+
return;
|
|
1055
1078
|
}
|
|
1079
|
+
if (options.securityPolicies.indexOf(securityPolicy) >= 0 && options.userTokenTypes.indexOf(tokenType) >= 0) {
|
|
1080
|
+
userIdentityTokens.push(r);
|
|
1081
|
+
}
|
|
1082
|
+
};
|
|
1083
|
+
|
|
1084
|
+
if (!options.noUserIdentityTokens) {
|
|
1085
|
+
if (options.securityPolicy === SecurityPolicy.None) {
|
|
1086
|
+
if (options.allowUnsecurePassword) {
|
|
1087
|
+
registerIdentity({
|
|
1088
|
+
policyId: u("username_unsecure"),
|
|
1089
|
+
tokenType: UserTokenType.UserName,
|
|
1056
1090
|
|
|
1057
|
-
const a = (tokenType: UserTokenType, securityPolicy: SecurityPolicy, name: string) => {
|
|
1058
|
-
if (options.securityPolicies.indexOf(securityPolicy) >= 0) {
|
|
1059
|
-
userIdentityTokens.push({
|
|
1060
|
-
policyId: u(name),
|
|
1061
|
-
tokenType,
|
|
1062
1091
|
issuedTokenType: null,
|
|
1063
1092
|
issuerEndpointUrl: null,
|
|
1064
|
-
securityPolicyUri:
|
|
1093
|
+
securityPolicyUri: null
|
|
1065
1094
|
});
|
|
1066
1095
|
}
|
|
1067
|
-
};
|
|
1068
|
-
const onlyCertificateLessConnection =
|
|
1069
|
-
options.onlyCertificateLessConnection === undefined ? false : options.onlyCertificateLessConnection;
|
|
1070
|
-
|
|
1071
|
-
if (!onlyCertificateLessConnection) {
|
|
1072
|
-
a(UserTokenType.UserName, SecurityPolicy.Basic256, "username_basic256");
|
|
1073
|
-
a(UserTokenType.UserName, SecurityPolicy.Basic128Rsa15, "username_basic128Rsa15");
|
|
1074
|
-
a(UserTokenType.UserName, SecurityPolicy.Basic256Sha256, "username_basic256Sha256");
|
|
1075
|
-
a(UserTokenType.UserName, SecurityPolicy.Aes128_Sha256_RsaOaep, "username_aes128Sha256RsaOaep");
|
|
1076
|
-
|
|
1077
|
-
// X509
|
|
1078
|
-
a(UserTokenType.Certificate, SecurityPolicy.Basic256, "certificate_basic256");
|
|
1079
|
-
a(UserTokenType.Certificate, SecurityPolicy.Basic128Rsa15, "certificate_basic128Rsa15");
|
|
1080
|
-
a(UserTokenType.Certificate, SecurityPolicy.Basic256Sha256, "certificate_basic256Sha256");
|
|
1081
|
-
a(UserTokenType.Certificate, SecurityPolicy.Aes128_Sha256_RsaOaep, "certificate_aes128Sha256RsaOaep");
|
|
1082
|
-
}
|
|
1083
|
-
} else {
|
|
1084
|
-
// note:
|
|
1085
|
-
// when channel session security is not "None",
|
|
1086
|
-
// userIdentityTokens can be left to null.
|
|
1087
|
-
// in this case this mean that secure policy will be the same as connection security policy
|
|
1088
|
-
userIdentityTokens.push({
|
|
1089
|
-
policyId: u("usernamePassword"),
|
|
1090
|
-
tokenType: UserTokenType.UserName,
|
|
1091
1096
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1097
|
+
const onlyCertificateLessConnection =
|
|
1098
|
+
options.onlyCertificateLessConnection === undefined ? false : options.onlyCertificateLessConnection;
|
|
1099
|
+
|
|
1100
|
+
if (!onlyCertificateLessConnection) {
|
|
1101
|
+
registerIdentity2(UserTokenType.UserName, SecurityPolicy.Basic256, "username_basic256");
|
|
1102
|
+
registerIdentity2(UserTokenType.UserName, SecurityPolicy.Basic128Rsa15, "username_basic128Rsa15");
|
|
1103
|
+
registerIdentity2(UserTokenType.UserName, SecurityPolicy.Basic256Sha256, "username_basic256Sha256");
|
|
1104
|
+
registerIdentity2(UserTokenType.UserName, SecurityPolicy.Aes128_Sha256_RsaOaep, "username_aes128Sha256RsaOaep");
|
|
1105
|
+
|
|
1106
|
+
// X509
|
|
1107
|
+
registerIdentity2(UserTokenType.Certificate, SecurityPolicy.Basic256, "certificate_basic256");
|
|
1108
|
+
registerIdentity2(UserTokenType.Certificate, SecurityPolicy.Basic128Rsa15, "certificate_basic128Rsa15");
|
|
1109
|
+
registerIdentity2(UserTokenType.Certificate, SecurityPolicy.Basic256Sha256, "certificate_basic256Sha256");
|
|
1110
|
+
registerIdentity2(
|
|
1111
|
+
UserTokenType.Certificate,
|
|
1112
|
+
SecurityPolicy.Aes128_Sha256_RsaOaep,
|
|
1113
|
+
"certificate_aes128Sha256RsaOaep"
|
|
1114
|
+
);
|
|
1115
|
+
}
|
|
1116
|
+
} else {
|
|
1117
|
+
// note:
|
|
1118
|
+
// when channel session security is not "None",
|
|
1119
|
+
// userIdentityTokens can be left to null.
|
|
1120
|
+
// in this case this mean that secure policy will be the same as connection security policy
|
|
1121
|
+
registerIdentity({
|
|
1122
|
+
policyId: u("usernamePassword"),
|
|
1123
|
+
tokenType: UserTokenType.UserName,
|
|
1124
|
+
issuedTokenType: null,
|
|
1125
|
+
issuerEndpointUrl: null,
|
|
1126
|
+
securityPolicyUri: null
|
|
1127
|
+
});
|
|
1096
1128
|
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1129
|
+
registerIdentity({
|
|
1130
|
+
policyId: u("certificateX509"),
|
|
1131
|
+
tokenType: UserTokenType.Certificate,
|
|
1100
1132
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1133
|
+
issuedTokenType: null,
|
|
1134
|
+
issuerEndpointUrl: null,
|
|
1135
|
+
securityPolicyUri: null
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1106
1138
|
|
|
1107
|
-
|
|
1108
|
-
userIdentityTokens.push({
|
|
1139
|
+
registerIdentity({
|
|
1109
1140
|
policyId: u("anonymous"),
|
|
1110
1141
|
tokenType: UserTokenType.Anonymous,
|
|
1111
1142
|
|
|
@@ -1114,7 +1145,6 @@ function _makeEndpointDescription(options: MakeEndpointDescriptionOptions): Endp
|
|
|
1114
1145
|
securityPolicyUri: null
|
|
1115
1146
|
});
|
|
1116
1147
|
}
|
|
1117
|
-
|
|
1118
1148
|
// return the endpoint object
|
|
1119
1149
|
const endpoint = new EndpointDescription({
|
|
1120
1150
|
endpointUrl: options.endpointUrl,
|
|
@@ -1172,3 +1202,10 @@ const defaultSecurityPolicies = [
|
|
|
1172
1202
|
SecurityPolicy.Aes128_Sha256_RsaOaep
|
|
1173
1203
|
// NO USED YET SecurityPolicy.Aes256_Sha256_RsaPss
|
|
1174
1204
|
];
|
|
1205
|
+
|
|
1206
|
+
const defaultUserTokenTypes = [
|
|
1207
|
+
UserTokenType.Anonymous,
|
|
1208
|
+
UserTokenType.UserName,
|
|
1209
|
+
UserTokenType.Certificate
|
|
1210
|
+
// NOT USED YET : UserTokenType.IssuedToken
|
|
1211
|
+
];
|