node-opcua-role-set-server 2.174.0 → 2.175.1
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/README.md +38 -1
- package/dist/bind_user_management.js +3 -3
- package/dist/bind_user_management.js.map +1 -1
- package/dist/install_role_based_security.d.ts +23 -30
- package/dist/install_role_based_security.js +77 -3
- package/dist/install_role_based_security.js.map +1 -1
- package/dist/install_role_set.js +4 -1
- package/dist/install_role_set.js.map +1 -1
- package/dist/user_management_user_manager.d.ts +9 -3
- package/dist/user_management_user_manager.js +17 -14
- package/dist/user_management_user_manager.js.map +1 -1
- package/package.json +15 -14
- package/source/bind_user_management.ts +3 -3
- package/source/install_role_based_security.ts +89 -12
- package/source/install_role_set.ts +4 -1
- package/source/user_management_user_manager.ts +33 -17
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ in short:
|
|
|
75
75
|
import { createRoleBasedSecurity } from "node-opcua-role-set-server";
|
|
76
76
|
import { WellKnownRoleIds } from "node-opcua-role-set-common";
|
|
77
77
|
|
|
78
|
-
const security = createRoleBasedSecurity({
|
|
78
|
+
const security = await createRoleBasedSecurity({
|
|
79
79
|
users: [{ userName: "admin", password: "admin-pw1", roles: [WellKnownRoleIds.SecurityAdmin] }]
|
|
80
80
|
});
|
|
81
81
|
const server = new OPCUAServer({ /* … */ userManager: security.userManager });
|
|
@@ -83,6 +83,43 @@ await server.start();
|
|
|
83
83
|
await security.install(server, { persistencePath: "./config/role-set.json" });
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
`createRoleBasedSecurity` is **async** (it hashes any clear-text seed passwords)
|
|
87
|
+
and returns the shared stores plus the `userManager` bridge.
|
|
88
|
+
|
|
89
|
+
### Seeding without clear text, and password hashing
|
|
90
|
+
|
|
91
|
+
Each seeded user provides **one** of:
|
|
92
|
+
|
|
93
|
+
- `password` — clear text (hashed with scrypt on seed); or
|
|
94
|
+
- `passwordHash` — a pre-hashed credential record, so **no clear text lives in
|
|
95
|
+
config / version control**.
|
|
96
|
+
|
|
97
|
+
Build a record offline with the `node-opcua-role-set-common` helpers:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { serializeUser, credentialRecord } from "node-opcua-role-set-common";
|
|
101
|
+
|
|
102
|
+
// scrypt record from a clear password (run once at deploy time, commit the result)
|
|
103
|
+
const admin = await serializeUser("admin", "admin-pw1", { /* userConfiguration, description */ });
|
|
104
|
+
|
|
105
|
+
// or wrap an already-hashed credential you already hold (e.g. a legacy $2b$ bcrypt hash)
|
|
106
|
+
const legacy = credentialRecord("legacy", "$2b$10$……");
|
|
107
|
+
|
|
108
|
+
const security = await createRoleBasedSecurity({
|
|
109
|
+
users: [
|
|
110
|
+
{ userName: "admin", passwordHash: admin, roles: [WellKnownRoleIds.SecurityAdmin] },
|
|
111
|
+
{ userName: "legacy", passwordHash: legacy, roles: [WellKnownRoleIds.Operator] }
|
|
112
|
+
]
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Credentials are stored as self-describing PHC strings (`$scrypt$…` / `$2b$…`), so
|
|
117
|
+
schemes coexist: new/changed passwords hash with **scrypt** (Node core), while a
|
|
118
|
+
legacy **bcrypt** credential still verifies and is transparently re-hashed to
|
|
119
|
+
scrypt on the next successful login (*upgrade-on-login*). Pass a custom
|
|
120
|
+
`registry` to `createRoleBasedSecurity` to add schemes (e.g. an external
|
|
121
|
+
verifier). See [`node-opcua-role-set-common`](../node-opcua-role-set-common#users--password-hashing).
|
|
122
|
+
|
|
86
123
|
## Exports
|
|
87
124
|
|
|
88
125
|
| Export | Description |
|
|
@@ -26,7 +26,7 @@ function makeAddUserHandler(options) {
|
|
|
26
26
|
}
|
|
27
27
|
const userConfiguration = (0, variant_args_js_1.asMask)(inputArguments[2]);
|
|
28
28
|
const description = (0, variant_args_js_1.asString)(inputArguments[3]) ?? "";
|
|
29
|
-
const statusCode = store.addUser(userName, password, userConfiguration, description);
|
|
29
|
+
const statusCode = await store.addUser(userName, password, userConfiguration, description);
|
|
30
30
|
if (statusCode === node_opcua_status_code_1.StatusCodes.Good && onMutation) {
|
|
31
31
|
await onMutation();
|
|
32
32
|
}
|
|
@@ -56,7 +56,7 @@ function makeModifyUserHandler(options) {
|
|
|
56
56
|
}
|
|
57
57
|
const modifyUserConfiguration = (0, variant_args_js_1.asBoolean)(inputArguments[3]);
|
|
58
58
|
const userConfiguration = (0, variant_args_js_1.asMask)(inputArguments[4]);
|
|
59
|
-
const statusCode = store.modifyUser(userName, {
|
|
59
|
+
const statusCode = await store.modifyUser(userName, {
|
|
60
60
|
modifyPassword: (0, variant_args_js_1.asBoolean)(inputArguments[1]),
|
|
61
61
|
password: (0, variant_args_js_1.asString)(inputArguments[2]) ?? "",
|
|
62
62
|
modifyUserConfiguration,
|
|
@@ -136,7 +136,7 @@ function makeChangePasswordHandler(options) {
|
|
|
136
136
|
if (oldPassword === null || newPassword === null) {
|
|
137
137
|
return { statusCode: node_opcua_status_code_1.StatusCodes.BadInvalidArgument };
|
|
138
138
|
}
|
|
139
|
-
const statusCode = store.changePassword(userName, oldPassword, newPassword);
|
|
139
|
+
const statusCode = await store.changePassword(userName, oldPassword, newPassword);
|
|
140
140
|
if (statusCode === node_opcua_status_code_1.StatusCodes.Good && onMutation) {
|
|
141
141
|
await onMutation();
|
|
142
142
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind_user_management.js","sourceRoot":"","sources":["../source/bind_user_management.ts"],"names":[],"mappings":";;AAuDA,gDAiCC;AAGD,sDA8CC;AAGD,sDA+BC;AAQD,8DAmCC;AAvMD,mEAAsE;AACtE,uDAAgF;AAEhF,6DAAuF;AACvF,uDAAgE;AAgChE,MAAM,UAAU,GAAG,CAAC,IAA2B,EAAW,EAAE,CACxD,CAAC,IAAI,GAAG,wCAAqB,CAAC,QAAQ,CAAC,KAAK,wCAAqB,CAAC,QAAQ,CAAC;AAE/E,iDAAiD;AACjD,SAAgB,kBAAkB,CAAC,OAAkC;IACjE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC/C,OAAO,KAAK,UAAU,QAAQ,CAE1B,cAAyB,EACzB,OAAwB;QAExB,MAAM,QAAQ,GAAG,IAAA,0CAAqB,EAAC,OAAO,CAAC,CAAC;QAChD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAA,6CAAwB,EAAC,OAAO,CAAC,CAAC;QACjD,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,QAAQ,GAAG,IAAA,0BAAQ,EAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAA,0BAAQ,EAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACzC,OAAO,EAAE,UAAU,EAAE,oCAAW,CAAC,kBAAkB,EAAE,CAAC;QAC1D,CAAC;QACD,MAAM,iBAAiB,GAAG,IAAA,wBAAM,EAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,IAAA,0BAAQ,EAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEtD,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"bind_user_management.js","sourceRoot":"","sources":["../source/bind_user_management.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,39 +1,26 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module node-opcua-role-set-server
|
|
3
|
-
*
|
|
4
|
-
* One-call wiring for role-based security (OPC 10000-18) with a **single source
|
|
5
|
-
* of truth**. It owns one user store and one identity store and exposes them
|
|
6
|
-
* through the server `userManager` bridge — the only integration point the
|
|
7
|
-
* server core uses to resolve a session's Roles (`getUserRoles`) and to back
|
|
8
|
-
* each Role's `Identities` Property (`getIdentitiesForRole`).
|
|
9
|
-
*
|
|
10
|
-
* Because the `userManager` is created **before** the server (it is a
|
|
11
|
-
* constructor option) but the RoleSet / User Management Methods are installed
|
|
12
|
-
* **after** `server.start()`, this comes in two phases:
|
|
13
|
-
*
|
|
14
|
-
* ```ts
|
|
15
|
-
* const security = createRoleBasedSecurity({
|
|
16
|
-
* users: [{ userName: "admin", password: "pw", roles: [WellKnownRoleIds.SecurityAdmin] }]
|
|
17
|
-
* });
|
|
18
|
-
* const server = new OPCUAServer({ ..., userManager: security.userManager });
|
|
19
|
-
* await server.start();
|
|
20
|
-
* await security.install(server, { persistencePath: "./role-set.json" });
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
23
|
-
* Everything (resolution, the `Identities` Property, the AddIdentity/AddUser
|
|
24
|
-
* Methods, persistence) is backed by the same two stores, so the "legacy"
|
|
25
|
-
* (userManager) and "modern" (RoleSet Methods) views can never drift apart.
|
|
26
|
-
*/
|
|
27
1
|
import type { NodeId } from "node-opcua-nodeid";
|
|
28
|
-
import { ArchiveStore, InMemoryIdentityMappingStore, InMemoryUserManagementStore, type PasswordPolicy } from "node-opcua-role-set-common";
|
|
2
|
+
import { ArchiveStore, type HasherRegistry, InMemoryIdentityMappingStore, InMemoryUserManagementStore, type PasswordPolicy, type SerializedUserRecord } from "node-opcua-role-set-common";
|
|
29
3
|
import { UserConfigurationMask } from "node-opcua-types";
|
|
30
4
|
import { type InstallRoleSetResult, type IServerForRoleSet } from "./install_role_set.js";
|
|
31
5
|
import { type InstallUserManagementResult, type IServerForUserManagement } from "./install_user_management.js";
|
|
32
6
|
import { type IManagedUserManager } from "./user_management_user_manager.js";
|
|
33
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* A user to seed, with the well-known/custom Roles it holds.
|
|
9
|
+
*
|
|
10
|
+
* Provide **either** a clear-text {@link password} **or** a pre-hashed
|
|
11
|
+
* {@link passwordHash} (salted scrypt record from `serializeUser`) — the latter
|
|
12
|
+
* lets you seed users without any clear text in config/version control.
|
|
13
|
+
*/
|
|
34
14
|
export interface RoleBasedUser {
|
|
35
15
|
userName: string;
|
|
36
|
-
password
|
|
16
|
+
/** Clear-text seed password. Provide this or {@link passwordHash}. */
|
|
17
|
+
password?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Pre-hashed seed (salted scrypt record produced offline by `serializeUser`
|
|
20
|
+
* / `exportUsers`). Provide this or {@link password} — never both. Seeded
|
|
21
|
+
* verbatim via `importUsers`, so no clear text is required.
|
|
22
|
+
*/
|
|
23
|
+
passwordHash?: SerializedUserRecord;
|
|
37
24
|
/** Role NodeIds granted to this user (e.g. `WellKnownRoleIds.Operator`). */
|
|
38
25
|
roles?: NodeId[];
|
|
39
26
|
userConfiguration?: UserConfigurationMask;
|
|
@@ -44,6 +31,12 @@ export interface CreateRoleBasedSecurityOptions {
|
|
|
44
31
|
policy?: PasswordPolicy;
|
|
45
32
|
/** Users to seed up front (more can be added later via the Methods). */
|
|
46
33
|
users?: RoleBasedUser[];
|
|
34
|
+
/**
|
|
35
|
+
* Password-hashing registry. Omit for the default (scrypt hashes; bcrypt
|
|
36
|
+
* verifies legacy credentials and is upgraded to scrypt on login). Inject a
|
|
37
|
+
* custom {@link HasherRegistry} to add schemes (e.g. an external verifier).
|
|
38
|
+
*/
|
|
39
|
+
registry?: HasherRegistry;
|
|
47
40
|
}
|
|
48
41
|
export interface InstallRoleBasedSecurityOptions {
|
|
49
42
|
/** A shared archive coordinator. When omitted, one is built from `persistencePath`. */
|
|
@@ -75,4 +68,4 @@ export interface RoleBasedSecurity {
|
|
|
75
68
|
* users and their Roles. Pass `userManager` to the `OPCUAServer` constructor,
|
|
76
69
|
* then call {@link RoleBasedSecurity.install} after `server.start()`.
|
|
77
70
|
*/
|
|
78
|
-
export declare function createRoleBasedSecurity(options?: CreateRoleBasedSecurityOptions): RoleBasedSecurity
|
|
71
|
+
export declare function createRoleBasedSecurity(options?: CreateRoleBasedSecurityOptions): Promise<RoleBasedSecurity>;
|
|
@@ -1,22 +1,82 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createRoleBasedSecurity = createRoleBasedSecurity;
|
|
4
|
+
/**
|
|
5
|
+
* @module node-opcua-role-set-server
|
|
6
|
+
*
|
|
7
|
+
* One-call wiring for role-based security (OPC 10000-18) with a **single source
|
|
8
|
+
* of truth**. It owns one user store and one identity store and exposes them
|
|
9
|
+
* through the server `userManager` bridge — the only integration point the
|
|
10
|
+
* server core uses to resolve a session's Roles (`getUserRoles`) and to back
|
|
11
|
+
* each Role's `Identities` Property (`getIdentitiesForRole`).
|
|
12
|
+
*
|
|
13
|
+
* Because the `userManager` is created **before** the server (it is a
|
|
14
|
+
* constructor option) but the RoleSet / User Management Methods are installed
|
|
15
|
+
* **after** `server.start()`, this comes in two phases:
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* const security = await createRoleBasedSecurity({
|
|
19
|
+
* users: [{ userName: "admin", password: "pw", roles: [WellKnownRoleIds.SecurityAdmin] }]
|
|
20
|
+
* });
|
|
21
|
+
* const server = new OPCUAServer({ ..., userManager: security.userManager });
|
|
22
|
+
* await server.start();
|
|
23
|
+
* await security.install(server, { persistencePath: "./role-set.json" });
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Everything (resolution, the `Identities` Property, the AddIdentity/AddUser
|
|
27
|
+
* Methods, persistence) is backed by the same two stores, so the "legacy"
|
|
28
|
+
* (userManager) and "modern" (RoleSet Methods) views can never drift apart.
|
|
29
|
+
*/
|
|
30
|
+
const node_opcua_debug_1 = require("node-opcua-debug");
|
|
4
31
|
const node_opcua_role_set_common_1 = require("node-opcua-role-set-common");
|
|
5
32
|
const node_opcua_types_1 = require("node-opcua-types");
|
|
6
33
|
const install_role_set_js_1 = require("./install_role_set.js");
|
|
7
34
|
const install_user_management_js_1 = require("./install_user_management.js");
|
|
8
35
|
const user_management_user_manager_js_1 = require("./user_management_user_manager.js");
|
|
36
|
+
const errorLog = (0, node_opcua_debug_1.make_errorLog)("RoleBasedSecurity");
|
|
9
37
|
const userNameRule = (userName) => new node_opcua_types_1.IdentityMappingRuleType({ criteriaType: node_opcua_types_1.IdentityCriteriaType.UserName, criteria: userName });
|
|
10
38
|
/**
|
|
11
39
|
* Create the shared stores and the `userManager` bridge, seeding any initial
|
|
12
40
|
* users and their Roles. Pass `userManager` to the `OPCUAServer` constructor,
|
|
13
41
|
* then call {@link RoleBasedSecurity.install} after `server.start()`.
|
|
14
42
|
*/
|
|
15
|
-
function createRoleBasedSecurity(options) {
|
|
16
|
-
const userStore = new node_opcua_role_set_common_1.InMemoryUserManagementStore(options?.policy);
|
|
43
|
+
async function createRoleBasedSecurity(options) {
|
|
44
|
+
const userStore = new node_opcua_role_set_common_1.InMemoryUserManagementStore(options?.policy, options?.registry ? { registry: options.registry } : undefined);
|
|
17
45
|
const identityStore = new node_opcua_role_set_common_1.InMemoryIdentityMappingStore();
|
|
18
46
|
for (const user of options?.users ?? []) {
|
|
19
|
-
|
|
47
|
+
// Exactly one of password / passwordHash — reject the ambiguous case up
|
|
48
|
+
// front rather than silently preferring one (the docstring says "never
|
|
49
|
+
// both"), so a misconfiguration is loud instead of a silent surprise.
|
|
50
|
+
if (user.password !== undefined && user.passwordHash) {
|
|
51
|
+
throw new Error(`RoleBasedUser "${user.userName}": provide either "password" (clear text) or "passwordHash" (pre-hashed record), not both.`);
|
|
52
|
+
}
|
|
53
|
+
if (user.passwordHash) {
|
|
54
|
+
// Pre-hashed seed: import the credential record verbatim — no clear
|
|
55
|
+
// text involved. `userName`/`userConfiguration`/`description` on the
|
|
56
|
+
// RoleBasedUser take precedence over the record's own fields.
|
|
57
|
+
const userConfiguration = user.userConfiguration ?? user.passwordHash.userConfiguration;
|
|
58
|
+
// importUsers bypasses addUser's validation, so apply the same
|
|
59
|
+
// UserConfigurationMask check here (e.g. MustChangePassword +
|
|
60
|
+
// NoChangeByUser is an illegal combination — §5.2.3).
|
|
61
|
+
const configError = (0, node_opcua_role_set_common_1.validateUserConfiguration)(userConfiguration);
|
|
62
|
+
if (configError) {
|
|
63
|
+
throw new Error(`RoleBasedUser "${user.userName}": invalid userConfiguration (${configError.name}).`);
|
|
64
|
+
}
|
|
65
|
+
userStore.importUsers?.([
|
|
66
|
+
{
|
|
67
|
+
...user.passwordHash,
|
|
68
|
+
userName: user.userName,
|
|
69
|
+
userConfiguration,
|
|
70
|
+
description: user.description ?? user.passwordHash.description
|
|
71
|
+
}
|
|
72
|
+
]);
|
|
73
|
+
}
|
|
74
|
+
else if (user.password !== undefined) {
|
|
75
|
+
await userStore.addUser(user.userName, user.password, user.userConfiguration ?? node_opcua_types_1.UserConfigurationMask.None, user.description ?? "");
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
throw new Error(`RoleBasedUser "${user.userName}": provide either "password" (clear text) or "passwordHash" (pre-hashed record).`);
|
|
79
|
+
}
|
|
20
80
|
for (const role of user.roles ?? []) {
|
|
21
81
|
identityStore.addIdentity(role, userNameRule(user.userName));
|
|
22
82
|
}
|
|
@@ -32,6 +92,20 @@ function createRoleBasedSecurity(options) {
|
|
|
32
92
|
(installOptions?.persistencePath
|
|
33
93
|
? new node_opcua_role_set_common_1.ArchiveStore(installOptions.persistencePath, { secret: installOptions.persistenceSecret })
|
|
34
94
|
: undefined);
|
|
95
|
+
// Persist upgrade-on-login re-hashes (e.g. bcrypt → scrypt) so the
|
|
96
|
+
// migration sticks across restarts.
|
|
97
|
+
if (persistence) {
|
|
98
|
+
userStore.setOnCredentialUpgraded?.(() => {
|
|
99
|
+
// Background flush: a failed save must not surface as a
|
|
100
|
+
// process-level unhandled rejection. The upgraded credential
|
|
101
|
+
// is already live in memory; it will be re-persisted on the
|
|
102
|
+
// next login/mutation, so log and move on.
|
|
103
|
+
persistence.save().catch((err) => {
|
|
104
|
+
// Log the message only — a minified/obfuscated stack is noise.
|
|
105
|
+
errorLog("createRoleBasedSecurity: failed to persist credential upgrade:", err instanceof Error ? err.message : err);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
35
109
|
const roleSet = await (0, install_role_set_js_1.installRoleSet)(server, { store: identityStore, persistence });
|
|
36
110
|
const userManagement = await (0, install_user_management_js_1.installUserManagement)(server, { store: userStore, persistence });
|
|
37
111
|
return { roleSet, userManagement };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install_role_based_security.js","sourceRoot":"","sources":["../source/install_role_based_security.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"install_role_based_security.js","sourceRoot":"","sources":["../source/install_role_based_security.ts"],"names":[],"mappings":";;AAuHA,0DAuFC;AA9MD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,uDAAiD;AAEjD,2EAQoC;AACpC,uDAAwG;AACxG,+DAA0G;AAC1G,6EAIsC;AACtC,uFAAgG;AAEhG,MAAM,QAAQ,GAAG,IAAA,gCAAa,EAAC,mBAAmB,CAAC,CAAC;AAiEpD,MAAM,YAAY,GAAG,CAAC,QAAgB,EAA2B,EAAE,CAC/D,IAAI,0CAAuB,CAAC,EAAE,YAAY,EAAE,uCAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;AAErG;;;;GAIG;AACI,KAAK,UAAU,uBAAuB,CAAC,OAAwC;IAClF,MAAM,SAAS,GAAG,IAAI,wDAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACnI,MAAM,aAAa,GAAG,IAAI,yDAA4B,EAAE,CAAC;IAEzD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;QACtC,wEAAwE;QACxE,uEAAuE;QACvE,sEAAsE;QACtE,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACnD,MAAM,IAAI,KAAK,CACX,kBAAkB,IAAI,CAAC,QAAQ,4FAA4F,CAC9H,CAAC;QACN,CAAC;QACD,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,oEAAoE;YACpE,qEAAqE;YACrE,8DAA8D;YAC9D,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC;YACxF,+DAA+D;YAC/D,8DAA8D;YAC9D,sDAAsD;YACtD,MAAM,WAAW,GAAG,IAAA,sDAAyB,EAAC,iBAAiB,CAAC,CAAC;YACjE,IAAI,WAAW,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CACX,kBAAkB,IAAI,CAAC,QAAQ,iCAAiC,WAAW,CAAC,IAAI,IAAI,CACvF,CAAC;YACN,CAAC;YACD,SAAS,CAAC,WAAW,EAAE,CAAC;gBACpB;oBACI,GAAG,IAAI,CAAC,YAAY;oBACpB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,iBAAiB;oBACjB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,YAAY,CAAC,WAAW;iBACjE;aACJ,CAAC,CAAC;QACP,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,SAAS,CAAC,OAAO,CACnB,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,iBAAiB,IAAI,wCAAqB,CAAC,IAAI,EACpD,IAAI,CAAC,WAAW,IAAI,EAAE,CACzB,CAAC;QACN,CAAC;aAAM,CAAC;YACJ,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,CAAC,QAAQ,kFAAkF,CAAC,CAAC;QACvI,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YAClC,aAAa,CAAC,WAAW,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACjE,CAAC;IACL,CAAC;IAED,MAAM,WAAW,GAAG,IAAA,mDAAiB,EAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAEhE,OAAO;QACH,SAAS;QACT,aAAa;QACb,WAAW;QACX,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc;YAChC,gFAAgF;YAChF,MAAM,WAAW,GACb,cAAc,EAAE,WAAW;gBAC3B,CAAC,cAAc,EAAE,eAAe;oBAC5B,CAAC,CAAC,IAAI,yCAAY,CAAC,cAAc,CAAC,eAAe,EAAE,EAAE,MAAM,EAAE,cAAc,CAAC,iBAAiB,EAAE,CAAC;oBAChG,CAAC,CAAC,SAAS,CAAC,CAAC;YAErB,mEAAmE;YACnE,oCAAoC;YACpC,IAAI,WAAW,EAAE,CAAC;gBACd,SAAS,CAAC,uBAAuB,EAAE,CAAC,GAAG,EAAE;oBACrC,wDAAwD;oBACxD,6DAA6D;oBAC7D,4DAA4D;oBAC5D,2CAA2C;oBAC3C,WAAW,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;wBAC7B,+DAA+D;wBAC/D,QAAQ,CACJ,gEAAgE,EAChE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAC3C,CAAC;oBACN,CAAC,CAAC,CAAC;gBACP,CAAC,CAAC,CAAC;YACP,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,IAAA,oCAAc,EAAC,MAAM,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,CAAC;YACpF,MAAM,cAAc,GAAG,MAAM,IAAA,kDAAqB,EAAC,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC;YAC9F,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;QACvC,CAAC;KACJ,CAAC;AACN,CAAC"}
|
package/dist/install_role_set.js
CHANGED
|
@@ -82,9 +82,12 @@ async function installRoleSet(server, options) {
|
|
|
82
82
|
server.roleResolvers ??= [];
|
|
83
83
|
server.roleResolvers.push(resolver);
|
|
84
84
|
function refreshIdentities(role) {
|
|
85
|
+
console.log(`[REFRESH] role: ${role.browseName.toString()}, nodeId: ${role.nodeId.toString()}`);
|
|
86
|
+
const identities = store.getIdentitiesForRole(role.nodeId);
|
|
87
|
+
console.log(`[REFRESH] identities for ${role.nodeId.toString()}:`, JSON.stringify(identities));
|
|
85
88
|
role.identities.setValueFromSource({
|
|
86
89
|
dataType: node_opcua_variant_1.DataType.ExtensionObject,
|
|
87
|
-
value:
|
|
90
|
+
value: identities
|
|
88
91
|
});
|
|
89
92
|
}
|
|
90
93
|
/** Refresh a Role's Applications/Endpoints restriction variables from the store. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install_role_set.js","sourceRoot":"","sources":["../source/install_role_set.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"install_role_set.js","sourceRoot":"","sources":["../source/install_role_set.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;AA8HH,wCA0RC;AAtZD,6CAAyC;AAEzC,+DAAiD;AACjD,iEAAkD;AAClD,yDAAkF;AAClF,2EAYoC;AAEpC,mEAAqD;AACrD,uDAAgD;AAEhD,2DAAgE;AAChE,yCAAmD;AACnD,+EAMuC;AACvC,iEAKgC;AAChC,2CAA8C;AAC9C,iEAAyD;AACzD,6DAAuF;AACvF,uDAA6C;AAE7C,MAAM,gBAAgB,GAAG,8BAA8B,CAAC;AAKxD,6EAA6E;AAC7E,SAAS,WAAW,CAAC,OAAkB,EAAE,EAA0B;IAC/D,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QACtC,IAAI,CAAC,CAAC,SAAS,KAAK,iCAAS,CAAC,MAAM;YAAE,SAAS;QAC/C,MAAM,GAAG,GAAG,CAAa,CAAC;QAC1B,IAAI,GAAG,CAAC,iBAAiB,CAAC,UAAU,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QACnE,EAAE,CAAC,GAAa,CAAC,CAAC;IACtB,CAAC;AACL,CAAC;AAED,kFAAkF;AAClF,SAAS,qBAAqB,CAAC,MAAc;IACzC,IAAI,MAAM,CAAC,SAAS,KAAK,CAAC,IAAI,MAAM,CAAC,cAAc,KAAK,8BAAU,CAAC,OAAO,EAAE,CAAC;QACzE,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,2CAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;IAC/F,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAe,CAAC,CAAC;AACnD,CAAC;AAED,sEAAsE;AACtE,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2CAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAqD1G;;;GAGG;AACI,KAAK,UAAU,cAAc,CAAC,MAAyB,EAAE,OAA+B;IAC3F,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;IAChD,IAAI,CAAC,YAAY,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;IACvG,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,gCAAS,CAAC,iCAAiC,CAAqB,CAAC;IACvG,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IAC1F,CAAC;IAED,8EAA8E;IAC9E,gFAAgF;IAChF,MAAM,WAAW,GACb,OAAO,EAAE,WAAW;QACpB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,yCAAY,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAE9H,8EAA8E;IAC9E,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAEnE,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,IAAI,yDAA4B,EAAE,CAAC;IACnE,IAAA,iDAAoB,EAAC,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAEjD,MAAM,gBAAgB,GAAG,IAAI,yDAA4B,EAAE,CAAC;IAC5D,IAAI,OAAO,EAAE,YAAY,EAAE,CAAC;QACxB,IAAA,oDAAuB,EAAC,gBAAgB,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,sCAAe,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAC9D,MAAM,CAAC,aAAa,KAAK,EAAE,CAAC;IAC5B,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEpC,SAAS,iBAAiB,CAAC,IAAY;QACnC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,aAAa,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAChG,MAAM,UAAU,GAAG,KAAK,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,4BAA4B,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;QAC/F,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC;YAC/B,QAAQ,EAAE,6BAAQ,CAAC,eAAe;YAClC,KAAK,EAAE,UAAU;SACpB,CAAC,CAAC;IACP,CAAC;IAED,oFAAoF;IACpF,SAAS,mBAAmB,CAAC,IAAY;QACrC,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC;YAClC,QAAQ,EAAE,6BAAQ,CAAC,MAAM;YACzB,SAAS,EAAE,qCAAgB,CAAC,KAAK;YACjC,KAAK,EAAE,gBAAgB,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;SACvD,CAAC,CAAC;QACH,IAAI,CAAC,mBAAmB,EAAE,kBAAkB,CAAC;YACzC,QAAQ,EAAE,6BAAQ,CAAC,OAAO;YAC1B,KAAK,EAAE,gBAAgB,CAAC,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC;SAC9D,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC;YAC/B,QAAQ,EAAE,6BAAQ,CAAC,eAAe;YAClC,SAAS,EAAE,qCAAgB,CAAC,KAAK;YACjC,KAAK,EAAE,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,+BAAY,CAAC,CAAC,CAAC,CAAC;SACpF,CAAC,CAAC;QACH,IAAI,CAAC,gBAAgB,EAAE,kBAAkB,CAAC;YACtC,QAAQ,EAAE,6BAAQ,CAAC,OAAO;YAC1B,KAAK,EAAE,gBAAgB,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC;SAC3D,CAAC,CAAC;IACP,CAAC;IAED,MAAM,WAAW,GAAoB,EAAE,CAAC;IAExC,8EAA8E;IAC9E,6EAA6E;IAC7E,WAAW,EAAE,qBAAqB,CAAC,GAAG,EAAE,CAAC,IAAA,+CAAkB,EAAC,KAAK,CAAC,CAAC,CAAC;IACpE,WAAW,EAAE,gBAAgB,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC;IACjD,WAAW,EAAE,uBAAuB,CAAC,GAAG,EAAE,CAAC,IAAA,kDAAqB,EAAC,gBAAgB,CAAC,CAAC,CAAC;IAEpF,gFAAgF;IAChF,KAAK,UAAU,OAAO;QAClB,MAAM,WAAW,EAAE,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED,0EAA0E;IAC1E,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE;QAC7B,WAAW,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAC1B,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACxB,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,MAAM,OAAO,EAAE,CAAC;IACpB,CAAC,CAAC;IAEF,4EAA4E;IAC5E,gEAAgE;IAChE,MAAM,YAAY,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC;IAC9D,MAAM,qBAAqB,GAAG,CAAC,KAAkC,EAAQ,EAAE;QACvE,IAAA,gCAAqB,EAAC,YAAY,EAAE,sCAAsC,EAAE;YACxE,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,UAAU,EAAE,UAAU,KAAK,CAAC,MAAM,EAAE;YACpC,QAAQ,EAAE,KAAK,CAAC,YAAY;YAC5B,YAAY,EAAE,KAAK,CAAC,QAAQ;YAC5B,MAAM,EAAE,KAAK,CAAC,UAAU,KAAK,oCAAW,CAAC,IAAI;YAC7C,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,KAAK,CAAC,QAAQ,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE;YACnH,cAAc,EAAE,KAAK,CAAC,cAAc;SACvC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,MAAM,aAAa,GAA2B,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACnH,MAAM,kBAAkB,GAAG,IAAA,6CAAsB,EAAC,aAAa,CAAC,CAAC;IACjE,MAAM,qBAAqB,GAAG,IAAA,gDAAyB,EAAC,aAAa,CAAC,CAAC;IAEvE,MAAM,wBAAwB,GAAkC;QAC5D,gBAAgB;QAChB,UAAU,EAAE,aAAa;QACzB,OAAO,EAAE,qBAAqB;KACjC,CAAC;IACF,MAAM,qBAAqB,GAAG,IAAA,uDAAyB,EAAC,wBAAwB,CAAC,CAAC;IAClF,MAAM,wBAAwB,GAAG,IAAA,0DAA4B,EAAC,wBAAwB,CAAC,CAAC;IACxF,MAAM,kBAAkB,GAAG,IAAA,oDAAsB,EAAC,wBAAwB,CAAC,CAAC;IAC5E,MAAM,qBAAqB,GAAG,IAAA,uDAAyB,EAAC,wBAAwB,CAAC,CAAC;IAElF,gFAAgF;IAChF,SAAS,eAAe,CAAC,IAAY;QACjC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACxB,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,kBAAkB,CAAC,CAAC;QACjD,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,qBAAqB,CAAC,CAAC;QACvD,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,qBAAqB,CAAC,CAAC;QACvD,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,wBAAwB,CAAC,CAAC;QAC7D,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,kBAAkB,CAAC,CAAC;QACjD,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,qBAAqB,CAAC,CAAC;QACvD,UAAU,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACH,SAAS,UAAU,CAAC,IAAY;QAC5B,IAAA,2BAAe,EAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACjC,IAAA,2BAAe,EAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACnC,IAAA,2BAAe,EAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC1C,IAAA,2BAAe,EAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAChC,IAAA,2BAAe,EAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACvC,IAAA,2BAAe,EAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClC,IAAA,2BAAe,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACrC,IAAA,2BAAe,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACrC,IAAA,2BAAe,EAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACxC,IAAA,2BAAe,EAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClC,IAAA,2BAAe,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC;IAED,+EAA+E;IAC/E,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAE,mBAA2B,EAAE,MAAc,EAAU,EAAE;QAC7F,MAAM,QAAQ,GAAG,YAAY,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC;YAC9B,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,mBAAmB,EAAE;YACnE,WAAW,EAAE,OAAO;YACpB,MAAM;YACN,SAAS,EAAE;gBACP,aAAa;gBACb,gBAAgB;gBAChB,gBAAgB;gBAChB,mBAAmB;gBACnB,aAAa;gBACb,gBAAgB;gBAChB,cAAc;gBACd,qBAAqB;gBACrB,WAAW;gBACX,kBAAkB;aACrB;SACJ,CAAW,CAAC;QACb,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC;IAEF,oEAAoE;IACpE,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,IAAA,iCAAa,EAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC,KAAK,CAAC;QAC1H,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAClD,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,+EAA+E;IAC/E,WAAW,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAEtC,mBAAmB;IACnB,MAAM,cAAc,GAAG,KAAK,WAExB,cAAyB,EACzB,OAAwB;QAExB,MAAM,QAAQ,GAAG,IAAA,0CAAqB,EAAC,OAAO,CAAC,CAAC;QAChD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAA,6CAAwB,EAAC,OAAO,CAAC,CAAC;QACjD,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,QAAQ,GAAG,IAAA,0BAAQ,EAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,OAAO,EAAE,UAAU,EAAE,oCAAW,CAAC,kBAAkB,EAAE,CAAC;QAC1D,CAAC;QACD,sEAAsE;QACtE,8DAA8D;QAC9D,IAAI,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtC,OAAO,EAAE,UAAU,EAAE,oCAAW,CAAC,gBAAgB,EAAE,CAAC;QACxD,CAAC;QACD,MAAM,YAAY,GAAG,IAAA,0BAAQ,EAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,MAAM,mBAAmB,GACrB,YAAY,IAAI,YAAY,KAAK,gBAAgB;YAC7C,CAAC,CAAC,eAAe,CAAC,YAAY,EAAE,YAAY,CAAC;YAC7C,CAAC,CAAC,YAAY,KAAK,gBAAgB;gBACjC,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC,KAAK,CAAC;QAEjD,uEAAuE;QACvE,0EAA0E;QAC1E,4EAA4E;QAC5E,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACnF,IAAI,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,UAAU,EAAE,oCAAW,CAAC,gBAAgB,EAAE,CAAC;QACxD,CAAC;QAED,yEAAyE;QACzE,MAAM,MAAM,GAAG,IAAI,0BAAM,CAAC,8BAAU,CAAC,IAAI,EAAE,IAAA,wBAAU,GAAE,CAAC,WAAW,EAAE,EAAE,YAAY,CAAC,eAAe,EAAE,CAAC,KAAK,CAAC,CAAC;QAC7G,cAAc,CAAC,QAAQ,EAAE,mBAAmB,EAAE,MAAM,CAAC,CAAC;QAEtD,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;QACxE,MAAM,OAAO,EAAE,CAAC;QAEhB,OAAO;YACH,UAAU,EAAE,oCAAW,CAAC,IAAI;YAC5B,eAAe,EAAE,CAAC,EAAE,QAAQ,EAAE,6BAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;SAClE,CAAC;IACN,CAAC,CAAC;IAEF,sBAAsB;IACtB,MAAM,iBAAiB,GAAG,KAAK,WAE3B,cAAyB,EACzB,OAAwB;QAExB,MAAM,QAAQ,GAAG,IAAA,0CAAqB,EAAC,OAAO,CAAC,CAAC;QAChD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAA,6CAAwB,EAAC,OAAO,CAAC,CAAC;QACjD,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;QAC5C,IAAI,CAAC,CAAC,UAAU,YAAY,0BAAM,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,UAAU,EAAE,oCAAW,CAAC,kBAAkB,EAAE,CAAC;QAC1D,CAAC;QACD,2EAA2E;QAC3E,IAAI,qBAAqB,CAAC,UAAU,CAAC,EAAE,CAAC;YACpC,OAAO,EAAE,UAAU,EAAE,oCAAW,CAAC,oBAAoB,EAAE,CAAC;QAC5D,CAAC;QACD,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAkB,CAAC;QAChE,IAAI,IAAI,EAAE,iBAAiB,EAAE,UAAU,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC1D,OAAO,EAAE,UAAU,EAAE,oCAAW,CAAC,gBAAgB,EAAE,CAAC;QACxD,CAAC;QAED,sEAAsE;QACtE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC;YACxD,KAAK,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC;QACD,YAAY,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,8BAAU,EAAC,IAAA,iCAAa,EAAC,CAAC,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;QAC1F,IAAI,GAAG,IAAI,CAAC;YAAE,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAEzC,MAAM,OAAO,EAAE,CAAC;QAChB,OAAO,EAAE,UAAU,EAAE,oCAAW,CAAC,IAAI,EAAE,CAAC;IAC5C,CAAC,CAAC;IAEF,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,CAAC,OAAoB,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QACzD,IAAA,2BAAe,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACpB,OAAO,CAAC,UAAuB,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QAC/D,IAAA,2BAAe,EAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC;AACjD,CAAC;AAED,yEAAyE;AACzE,SAAS,eAAe,CAAC,YAA2B,EAAE,YAAoB;IACtE,MAAM,GAAG,GAAG,YAAY,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;IACzD,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC;AAC/E,CAAC"}
|
|
@@ -2,15 +2,21 @@ import { type NodeId, type NodeIdLike } from "node-opcua-nodeid";
|
|
|
2
2
|
import type { IIdentityMappingStore, IUserManagementStore } from "node-opcua-role-set-common";
|
|
3
3
|
import { type StatusCode } from "node-opcua-status-code";
|
|
4
4
|
import { type IdentityMappingRuleType } from "node-opcua-types";
|
|
5
|
-
/** The subset of the ServerSession that `
|
|
5
|
+
/** The subset of the ServerSession that `isValidUserAsync` is bound to (`this`). */
|
|
6
6
|
interface SessionThis {
|
|
7
7
|
getSessionId?(): NodeId;
|
|
8
8
|
/** Set so ActivateSession returns Good_PasswordChangeRequired (node-opcua-server). */
|
|
9
9
|
passwordChangeRequired?: boolean;
|
|
10
10
|
}
|
|
11
|
+
/** node-opcua's callback-style credential check (`ValidUserAsyncFunc`). */
|
|
12
|
+
type ValidUserCallback = (err: Error | null, isAuthorized?: boolean) => void;
|
|
11
13
|
export interface IManagedUserManager {
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Validate credentials (async, callback-style — the shape node-opcua's
|
|
16
|
+
* `isValidUserAsync` option expects, so an external verifier can be plugged
|
|
17
|
+
* in). Invokes the callback with `true` for Good and Good_PasswordChangeRequired.
|
|
18
|
+
*/
|
|
19
|
+
isValidUserAsync(this: SessionThis, userName: string, password: string, callback: ValidUserCallback): void;
|
|
14
20
|
/** Resolve the Roles granted to a user (only Anonymous while a change is required). */
|
|
15
21
|
getUserRoles(userName: string): NodeId[];
|
|
16
22
|
/**
|
|
@@ -39,20 +39,23 @@ function createUserManager(userStore, identityStore) {
|
|
|
39
39
|
getSessionAuthStatus(sessionId) {
|
|
40
40
|
return statusBySession.get(sessionId.toString());
|
|
41
41
|
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
42
|
+
isValidUserAsync(userName, password, callback) {
|
|
43
|
+
// `this` is the ServerSession; the arrow callbacks below preserve it
|
|
44
|
+
// across the async boundary.
|
|
45
|
+
userStore.authenticate(userName, password).then((result) => {
|
|
46
|
+
lastAuthStatus.set(userName, result.statusCode);
|
|
47
|
+
// key the status by the SessionId the client also holds, so the
|
|
48
|
+
// outcome can be observed per session.
|
|
49
|
+
const sessionId = this?.getSessionId?.();
|
|
50
|
+
if (sessionId) {
|
|
51
|
+
statusBySession.set(sessionId.toString(), result.statusCode);
|
|
52
|
+
}
|
|
53
|
+
// flag the session so ActivateSession returns Good_PasswordChangeRequired
|
|
54
|
+
if (this) {
|
|
55
|
+
this.passwordChangeRequired = result.statusCode === node_opcua_status_code_1.StatusCodes.GoodPasswordChangeRequired;
|
|
56
|
+
}
|
|
57
|
+
callback(null, result.statusCode === node_opcua_status_code_1.StatusCodes.Good || result.statusCode === node_opcua_status_code_1.StatusCodes.GoodPasswordChangeRequired);
|
|
58
|
+
}, (err) => callback(err instanceof Error ? err : new Error(String(err))));
|
|
56
59
|
},
|
|
57
60
|
getUserRoles(userName) {
|
|
58
61
|
const user = userStore.getUsers().find((u) => u.userName === userName);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user_management_user_manager.js","sourceRoot":"","sources":["../source/user_management_user_manager.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"user_management_user_manager.js","sourceRoot":"","sources":["../source/user_management_user_manager.ts"],"names":[],"mappings":";;AAmEA,8CAoDC;AAvHD;;;;;;;;;;;;;;;;;;GAkBG;AACH,+DAAsD;AACtD,yDAA6E;AAE7E,mEAAsE;AACtE,uDAA8G;AAqC9G,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,GAAW,EAAW,EAAE,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC;AAEzE;;;;GAIG;AACH,SAAgB,iBAAiB,CAAC,SAA+B,EAAE,aAAoC;IACnG,MAAM,cAAc,GAAG,IAAI,GAAG,EAAsB,CAAC;IACrD,MAAM,eAAe,GAAG,IAAI,GAAG,EAAsB,CAAC;IACtD,MAAM,aAAa,GAAG,GAAa,EAAE,CAAC,CAAC,IAAA,8BAAU,EAAC,qCAAc,CAAC,SAAS,CAAC,CAAC,CAAC;IAE7E,OAAO;QACH,cAAc;QAEd,oBAAoB,CAAC,SAAqB;YACtC,OAAO,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,gBAAgB,CAAoB,QAAgB,EAAE,QAAgB,EAAE,QAA2B;YAC/F,qEAAqE;YACrE,6BAA6B;YAC7B,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,IAAI,CAC3C,CAAC,MAAM,EAAE,EAAE;gBACP,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;gBAChD,gEAAgE;gBAChE,uCAAuC;gBACvC,MAAM,SAAS,GAAG,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC;gBACzC,IAAI,SAAS,EAAE,CAAC;oBACZ,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;gBACjE,CAAC;gBACD,0EAA0E;gBAC1E,IAAI,IAAI,EAAE,CAAC;oBACP,IAAI,CAAC,sBAAsB,GAAG,MAAM,CAAC,UAAU,KAAK,oCAAW,CAAC,0BAA0B,CAAC;gBAC/F,CAAC;gBACD,QAAQ,CACJ,IAAI,EACJ,MAAM,CAAC,UAAU,KAAK,oCAAW,CAAC,IAAI,IAAI,MAAM,CAAC,UAAU,KAAK,oCAAW,CAAC,0BAA0B,CACzG,CAAC;YACN,CAAC,EACD,CAAC,GAAY,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAClF,CAAC;QACN,CAAC;QAED,YAAY,CAAC,QAAgB;YACzB,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;YACvE,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,wCAAqB,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAChF,OAAO,aAAa,EAAE,CAAC;YAC3B,CAAC;YACD,MAAM,KAAK,GAAyB,IAAI,wCAAqB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC5E,OAAO,aAAa,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC;QAED,oBAAoB,CAAC,IAAY;YAC7B,wEAAwE;YACxE,iEAAiE;YACjE,OAAO,aAAa,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACpD,CAAC;KACJ,CAAC;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-opcua-role-set-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.175.1",
|
|
4
4
|
"description": "pure nodejs OPCUA SDK - server-side role-set management (OPC 10000-18)",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsc -b",
|
|
@@ -16,20 +16,21 @@
|
|
|
16
16
|
"npm": ">=10.x"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"node-opcua-address-space": "2.
|
|
20
|
-
"node-opcua-address-space-base": "2.
|
|
21
|
-
"node-opcua-constants": "2.
|
|
22
|
-
"node-opcua-data-model": "2.
|
|
23
|
-
"node-opcua-
|
|
24
|
-
"node-opcua-
|
|
25
|
-
"node-opcua-
|
|
26
|
-
"node-opcua-
|
|
27
|
-
"node-opcua-
|
|
28
|
-
"node-opcua-
|
|
19
|
+
"node-opcua-address-space": "2.175.1",
|
|
20
|
+
"node-opcua-address-space-base": "2.175.1",
|
|
21
|
+
"node-opcua-constants": "2.175.1",
|
|
22
|
+
"node-opcua-data-model": "2.175.1",
|
|
23
|
+
"node-opcua-debug": "2.175.1",
|
|
24
|
+
"node-opcua-nodeid": "2.175.1",
|
|
25
|
+
"node-opcua-role-set-common": "2.175.1",
|
|
26
|
+
"node-opcua-service-call": "2.175.1",
|
|
27
|
+
"node-opcua-status-code": "2.175.1",
|
|
28
|
+
"node-opcua-types": "2.175.1",
|
|
29
|
+
"node-opcua-variant": "2.175.1"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
|
-
"node-opcua-leak-detector": "2.
|
|
32
|
-
"node-opcua-nodesets": "2.
|
|
32
|
+
"node-opcua-leak-detector": "2.175.1",
|
|
33
|
+
"node-opcua-nodesets": "2.175.1"
|
|
33
34
|
},
|
|
34
35
|
"author": "Etienne Rossignon",
|
|
35
36
|
"license": "MIT",
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
"internet of things"
|
|
47
48
|
],
|
|
48
49
|
"homepage": "http://node-opcua.github.io/",
|
|
49
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "7c0416a09c7fd83a034b4de3dc8197dff84b8ad8",
|
|
50
51
|
"files": [
|
|
51
52
|
"dist",
|
|
52
53
|
"source"
|
|
@@ -73,7 +73,7 @@ export function makeAddUserHandler(options: BindUserManagementOptions) {
|
|
|
73
73
|
const userConfiguration = asMask(inputArguments[2]);
|
|
74
74
|
const description = asString(inputArguments[3]) ?? "";
|
|
75
75
|
|
|
76
|
-
const statusCode = store.addUser(userName, password, userConfiguration, description);
|
|
76
|
+
const statusCode = await store.addUser(userName, password, userConfiguration, description);
|
|
77
77
|
if (statusCode === StatusCodes.Good && onMutation) {
|
|
78
78
|
await onMutation();
|
|
79
79
|
}
|
|
@@ -107,7 +107,7 @@ export function makeModifyUserHandler(options: BindUserManagementOptions) {
|
|
|
107
107
|
}
|
|
108
108
|
const modifyUserConfiguration = asBoolean(inputArguments[3]);
|
|
109
109
|
const userConfiguration = asMask(inputArguments[4]);
|
|
110
|
-
const statusCode = store.modifyUser(
|
|
110
|
+
const statusCode = await store.modifyUser(
|
|
111
111
|
userName,
|
|
112
112
|
{
|
|
113
113
|
modifyPassword: asBoolean(inputArguments[1]),
|
|
@@ -199,7 +199,7 @@ export function makeChangePasswordHandler(options: BindUserManagementOptions) {
|
|
|
199
199
|
return { statusCode: StatusCodes.BadInvalidArgument };
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
const statusCode = store.changePassword(userName, oldPassword, newPassword);
|
|
202
|
+
const statusCode = await store.changePassword(userName, oldPassword, newPassword);
|
|
203
203
|
if (statusCode === StatusCodes.Good && onMutation) {
|
|
204
204
|
await onMutation();
|
|
205
205
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* **after** `server.start()`, this comes in two phases:
|
|
13
13
|
*
|
|
14
14
|
* ```ts
|
|
15
|
-
* const security = createRoleBasedSecurity({
|
|
15
|
+
* const security = await createRoleBasedSecurity({
|
|
16
16
|
* users: [{ userName: "admin", password: "pw", roles: [WellKnownRoleIds.SecurityAdmin] }]
|
|
17
17
|
* });
|
|
18
18
|
* const server = new OPCUAServer({ ..., userManager: security.userManager });
|
|
@@ -24,12 +24,16 @@
|
|
|
24
24
|
* Methods, persistence) is backed by the same two stores, so the "legacy"
|
|
25
25
|
* (userManager) and "modern" (RoleSet Methods) views can never drift apart.
|
|
26
26
|
*/
|
|
27
|
+
import { make_errorLog } from "node-opcua-debug";
|
|
27
28
|
import type { NodeId } from "node-opcua-nodeid";
|
|
28
29
|
import {
|
|
29
30
|
ArchiveStore,
|
|
31
|
+
type HasherRegistry,
|
|
30
32
|
InMemoryIdentityMappingStore,
|
|
31
33
|
InMemoryUserManagementStore,
|
|
32
|
-
type PasswordPolicy
|
|
34
|
+
type PasswordPolicy,
|
|
35
|
+
type SerializedUserRecord,
|
|
36
|
+
validateUserConfiguration
|
|
33
37
|
} from "node-opcua-role-set-common";
|
|
34
38
|
import { IdentityCriteriaType, IdentityMappingRuleType, UserConfigurationMask } from "node-opcua-types";
|
|
35
39
|
import { type InstallRoleSetResult, type IServerForRoleSet, installRoleSet } from "./install_role_set.js";
|
|
@@ -40,10 +44,25 @@ import {
|
|
|
40
44
|
} from "./install_user_management.js";
|
|
41
45
|
import { createUserManager, type IManagedUserManager } from "./user_management_user_manager.js";
|
|
42
46
|
|
|
43
|
-
|
|
47
|
+
const errorLog = make_errorLog("RoleBasedSecurity");
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A user to seed, with the well-known/custom Roles it holds.
|
|
51
|
+
*
|
|
52
|
+
* Provide **either** a clear-text {@link password} **or** a pre-hashed
|
|
53
|
+
* {@link passwordHash} (salted scrypt record from `serializeUser`) — the latter
|
|
54
|
+
* lets you seed users without any clear text in config/version control.
|
|
55
|
+
*/
|
|
44
56
|
export interface RoleBasedUser {
|
|
45
57
|
userName: string;
|
|
46
|
-
password
|
|
58
|
+
/** Clear-text seed password. Provide this or {@link passwordHash}. */
|
|
59
|
+
password?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Pre-hashed seed (salted scrypt record produced offline by `serializeUser`
|
|
62
|
+
* / `exportUsers`). Provide this or {@link password} — never both. Seeded
|
|
63
|
+
* verbatim via `importUsers`, so no clear text is required.
|
|
64
|
+
*/
|
|
65
|
+
passwordHash?: SerializedUserRecord;
|
|
47
66
|
/** Role NodeIds granted to this user (e.g. `WellKnownRoleIds.Operator`). */
|
|
48
67
|
roles?: NodeId[];
|
|
49
68
|
userConfiguration?: UserConfigurationMask;
|
|
@@ -55,6 +74,12 @@ export interface CreateRoleBasedSecurityOptions {
|
|
|
55
74
|
policy?: PasswordPolicy;
|
|
56
75
|
/** Users to seed up front (more can be added later via the Methods). */
|
|
57
76
|
users?: RoleBasedUser[];
|
|
77
|
+
/**
|
|
78
|
+
* Password-hashing registry. Omit for the default (scrypt hashes; bcrypt
|
|
79
|
+
* verifies legacy credentials and is upgraded to scrypt on login). Inject a
|
|
80
|
+
* custom {@link HasherRegistry} to add schemes (e.g. an external verifier).
|
|
81
|
+
*/
|
|
82
|
+
registry?: HasherRegistry;
|
|
58
83
|
}
|
|
59
84
|
|
|
60
85
|
export interface InstallRoleBasedSecurityOptions {
|
|
@@ -92,17 +117,51 @@ const userNameRule = (userName: string): IdentityMappingRuleType =>
|
|
|
92
117
|
* users and their Roles. Pass `userManager` to the `OPCUAServer` constructor,
|
|
93
118
|
* then call {@link RoleBasedSecurity.install} after `server.start()`.
|
|
94
119
|
*/
|
|
95
|
-
export function createRoleBasedSecurity(options?: CreateRoleBasedSecurityOptions): RoleBasedSecurity {
|
|
96
|
-
const userStore = new InMemoryUserManagementStore(options?.policy);
|
|
120
|
+
export async function createRoleBasedSecurity(options?: CreateRoleBasedSecurityOptions): Promise<RoleBasedSecurity> {
|
|
121
|
+
const userStore = new InMemoryUserManagementStore(options?.policy, options?.registry ? { registry: options.registry } : undefined);
|
|
97
122
|
const identityStore = new InMemoryIdentityMappingStore();
|
|
98
123
|
|
|
99
124
|
for (const user of options?.users ?? []) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
125
|
+
// Exactly one of password / passwordHash — reject the ambiguous case up
|
|
126
|
+
// front rather than silently preferring one (the docstring says "never
|
|
127
|
+
// both"), so a misconfiguration is loud instead of a silent surprise.
|
|
128
|
+
if (user.password !== undefined && user.passwordHash) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`RoleBasedUser "${user.userName}": provide either "password" (clear text) or "passwordHash" (pre-hashed record), not both.`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
if (user.passwordHash) {
|
|
134
|
+
// Pre-hashed seed: import the credential record verbatim — no clear
|
|
135
|
+
// text involved. `userName`/`userConfiguration`/`description` on the
|
|
136
|
+
// RoleBasedUser take precedence over the record's own fields.
|
|
137
|
+
const userConfiguration = user.userConfiguration ?? user.passwordHash.userConfiguration;
|
|
138
|
+
// importUsers bypasses addUser's validation, so apply the same
|
|
139
|
+
// UserConfigurationMask check here (e.g. MustChangePassword +
|
|
140
|
+
// NoChangeByUser is an illegal combination — §5.2.3).
|
|
141
|
+
const configError = validateUserConfiguration(userConfiguration);
|
|
142
|
+
if (configError) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
`RoleBasedUser "${user.userName}": invalid userConfiguration (${configError.name}).`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
userStore.importUsers?.([
|
|
148
|
+
{
|
|
149
|
+
...user.passwordHash,
|
|
150
|
+
userName: user.userName,
|
|
151
|
+
userConfiguration,
|
|
152
|
+
description: user.description ?? user.passwordHash.description
|
|
153
|
+
}
|
|
154
|
+
]);
|
|
155
|
+
} else if (user.password !== undefined) {
|
|
156
|
+
await userStore.addUser(
|
|
157
|
+
user.userName,
|
|
158
|
+
user.password,
|
|
159
|
+
user.userConfiguration ?? UserConfigurationMask.None,
|
|
160
|
+
user.description ?? ""
|
|
161
|
+
);
|
|
162
|
+
} else {
|
|
163
|
+
throw new Error(`RoleBasedUser "${user.userName}": provide either "password" (clear text) or "passwordHash" (pre-hashed record).`);
|
|
164
|
+
}
|
|
106
165
|
for (const role of user.roles ?? []) {
|
|
107
166
|
identityStore.addIdentity(role, userNameRule(user.userName));
|
|
108
167
|
}
|
|
@@ -122,6 +181,24 @@ export function createRoleBasedSecurity(options?: CreateRoleBasedSecurityOptions
|
|
|
122
181
|
? new ArchiveStore(installOptions.persistencePath, { secret: installOptions.persistenceSecret })
|
|
123
182
|
: undefined);
|
|
124
183
|
|
|
184
|
+
// Persist upgrade-on-login re-hashes (e.g. bcrypt → scrypt) so the
|
|
185
|
+
// migration sticks across restarts.
|
|
186
|
+
if (persistence) {
|
|
187
|
+
userStore.setOnCredentialUpgraded?.(() => {
|
|
188
|
+
// Background flush: a failed save must not surface as a
|
|
189
|
+
// process-level unhandled rejection. The upgraded credential
|
|
190
|
+
// is already live in memory; it will be re-persisted on the
|
|
191
|
+
// next login/mutation, so log and move on.
|
|
192
|
+
persistence.save().catch((err) => {
|
|
193
|
+
// Log the message only — a minified/obfuscated stack is noise.
|
|
194
|
+
errorLog(
|
|
195
|
+
"createRoleBasedSecurity: failed to persist credential upgrade:",
|
|
196
|
+
err instanceof Error ? err.message : err
|
|
197
|
+
);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
125
202
|
const roleSet = await installRoleSet(server, { store: identityStore, persistence });
|
|
126
203
|
const userManagement = await installUserManagement(server, { store: userStore, persistence });
|
|
127
204
|
return { roleSet, userManagement };
|
|
@@ -171,9 +171,12 @@ export async function installRoleSet(server: IServerForRoleSet, options?: Instal
|
|
|
171
171
|
server.roleResolvers.push(resolver);
|
|
172
172
|
|
|
173
173
|
function refreshIdentities(role: UARole): void {
|
|
174
|
+
console.log(`[REFRESH] role: ${role.browseName.toString()}, nodeId: ${role.nodeId.toString()}`);
|
|
175
|
+
const identities = store.getIdentitiesForRole(role.nodeId);
|
|
176
|
+
console.log(`[REFRESH] identities for ${role.nodeId.toString()}:`, JSON.stringify(identities));
|
|
174
177
|
role.identities.setValueFromSource({
|
|
175
178
|
dataType: DataType.ExtensionObject,
|
|
176
|
-
value:
|
|
179
|
+
value: identities
|
|
177
180
|
});
|
|
178
181
|
}
|
|
179
182
|
|
|
@@ -23,16 +23,23 @@ import type { AnyUserIdentityToken, IIdentityMappingStore, IUserManagementStore
|
|
|
23
23
|
import { type StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
24
24
|
import { type IdentityMappingRuleType, UserConfigurationMask, UserNameIdentityToken } from "node-opcua-types";
|
|
25
25
|
|
|
26
|
-
/** The subset of the ServerSession that `
|
|
26
|
+
/** The subset of the ServerSession that `isValidUserAsync` is bound to (`this`). */
|
|
27
27
|
interface SessionThis {
|
|
28
28
|
getSessionId?(): NodeId;
|
|
29
29
|
/** Set so ActivateSession returns Good_PasswordChangeRequired (node-opcua-server). */
|
|
30
30
|
passwordChangeRequired?: boolean;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/** node-opcua's callback-style credential check (`ValidUserAsyncFunc`). */
|
|
34
|
+
type ValidUserCallback = (err: Error | null, isAuthorized?: boolean) => void;
|
|
35
|
+
|
|
33
36
|
export interface IManagedUserManager {
|
|
34
|
-
/**
|
|
35
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Validate credentials (async, callback-style — the shape node-opcua's
|
|
39
|
+
* `isValidUserAsync` option expects, so an external verifier can be plugged
|
|
40
|
+
* in). Invokes the callback with `true` for Good and Good_PasswordChangeRequired.
|
|
41
|
+
*/
|
|
42
|
+
isValidUserAsync(this: SessionThis, userName: string, password: string, callback: ValidUserCallback): void;
|
|
36
43
|
/** Resolve the Roles granted to a user (only Anonymous while a change is required). */
|
|
37
44
|
getUserRoles(userName: string): NodeId[];
|
|
38
45
|
/**
|
|
@@ -70,20 +77,29 @@ export function createUserManager(userStore: IUserManagementStore, identityStore
|
|
|
70
77
|
return statusBySession.get(sessionId.toString());
|
|
71
78
|
},
|
|
72
79
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
isValidUserAsync(this: SessionThis, userName: string, password: string, callback: ValidUserCallback): void {
|
|
81
|
+
// `this` is the ServerSession; the arrow callbacks below preserve it
|
|
82
|
+
// across the async boundary.
|
|
83
|
+
userStore.authenticate(userName, password).then(
|
|
84
|
+
(result) => {
|
|
85
|
+
lastAuthStatus.set(userName, result.statusCode);
|
|
86
|
+
// key the status by the SessionId the client also holds, so the
|
|
87
|
+
// outcome can be observed per session.
|
|
88
|
+
const sessionId = this?.getSessionId?.();
|
|
89
|
+
if (sessionId) {
|
|
90
|
+
statusBySession.set(sessionId.toString(), result.statusCode);
|
|
91
|
+
}
|
|
92
|
+
// flag the session so ActivateSession returns Good_PasswordChangeRequired
|
|
93
|
+
if (this) {
|
|
94
|
+
this.passwordChangeRequired = result.statusCode === StatusCodes.GoodPasswordChangeRequired;
|
|
95
|
+
}
|
|
96
|
+
callback(
|
|
97
|
+
null,
|
|
98
|
+
result.statusCode === StatusCodes.Good || result.statusCode === StatusCodes.GoodPasswordChangeRequired
|
|
99
|
+
);
|
|
100
|
+
},
|
|
101
|
+
(err: unknown) => callback(err instanceof Error ? err : new Error(String(err)))
|
|
102
|
+
);
|
|
87
103
|
},
|
|
88
104
|
|
|
89
105
|
getUserRoles(userName: string): NodeId[] {
|