@sonisoft/now-sdk-ext-core 6.17.1 → 6.18.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/dist/auth/NowSDKAuthenticationHandler.js +8 -1
- package/dist/auth/NowSDKAuthenticationHandler.js.map +1 -1
- package/dist/auth/SessionElevation.d.ts +54 -0
- package/dist/auth/SessionElevation.js +100 -0
- package/dist/auth/SessionElevation.js.map +1 -0
- package/dist/comm/http/FormHtmlParser.js +23 -7
- package/dist/comm/http/FormHtmlParser.js.map +1 -1
- package/dist/comm/http/FormRecordWriter.js +20 -4
- package/dist/comm/http/FormRecordWriter.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/sn/ServiceNowInstance.d.ts +9 -0
- package/dist/sn/ServiceNowInstance.js +4 -0
- package/dist/sn/ServiceNowInstance.js.map +1 -1
- package/dist/sn/metadata/MetadataFormWriter.d.ts +1 -0
- package/dist/sn/metadata/MetadataFormWriter.js +28 -6
- package/dist/sn/metadata/MetadataFormWriter.js.map +1 -1
- package/dist/sn/metadata/MetadataScopeError.d.ts +2 -2
- package/dist/sn/metadata/MetadataScopeError.js.map +1 -1
- package/dist/sn/metadata/internal/AccessControlWriters.d.ts +5 -0
- package/dist/sn/metadata/internal/AccessControlWriters.js +6 -0
- package/dist/sn/metadata/internal/AccessControlWriters.js.map +1 -0
- package/dist/sn/metadata/internal/MetadataFormActions.d.ts +1 -1
- package/dist/sn/metadata/internal/MetadataFormActions.js +9 -2
- package/dist/sn/metadata/internal/MetadataFormActions.js.map +1 -1
- package/dist/sn/metadata/internal/MetadataReader.d.ts +6 -1
- package/dist/sn/metadata/internal/MetadataReader.js +13 -2
- package/dist/sn/metadata/internal/MetadataReader.js.map +1 -1
- package/dist/sn/security/AclError.d.ts +21 -0
- package/dist/sn/security/AclError.js +35 -0
- package/dist/sn/security/AclError.js.map +1 -0
- package/dist/sn/security/AclManager.d.ts +54 -0
- package/dist/sn/security/AclManager.js +398 -0
- package/dist/sn/security/AclManager.js.map +1 -0
- package/dist/sn/security/AclModels.d.ts +102 -0
- package/dist/sn/security/AclModels.js +2 -0
- package/dist/sn/security/AclModels.js.map +1 -0
- package/dist/sn/security/RoleElevation.d.ts +16 -0
- package/dist/sn/security/RoleElevation.js +22 -0
- package/dist/sn/security/RoleElevation.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import { SessionManager } from '../../comm/http/SessionManager.js';
|
|
2
|
+
import { MetadataFormWriter } from '../metadata/MetadataFormWriter.js';
|
|
3
|
+
import { MetadataReader } from '../metadata/internal/MetadataReader.js';
|
|
4
|
+
import { resolveScope } from '../metadata/internal/MetadataScope.js';
|
|
5
|
+
import { AclError, AclPartialError } from './AclError.js';
|
|
6
|
+
import { RoleElevation } from './RoleElevation.js';
|
|
7
|
+
import { accessControlWriters } from '../metadata/internal/AccessControlWriters.js';
|
|
8
|
+
import { isPolicyRefusal } from '../../policy/PolicyRefusal.js';
|
|
9
|
+
const ID = /^[a-f0-9]{32}$/i;
|
|
10
|
+
const IDENT = /^[a-z0-9_]{1,80}$/i;
|
|
11
|
+
const ROLE = /^[a-z][a-z0-9_.]{0,79}$/i;
|
|
12
|
+
/** Free-form ACL names (REST endpoints, UI pages, …) must not break an encoded query. */
|
|
13
|
+
const RESOURCE = /^[^^\p{Cc}]{1,200}$/u;
|
|
14
|
+
/** A query value the instance would evaluate as script. */
|
|
15
|
+
const SCRIPT = /javascript:/i;
|
|
16
|
+
const ACL = 'sys_security_acl';
|
|
17
|
+
const ACL_ROLE = 'sys_security_acl_role';
|
|
18
|
+
const REQUIRED_ROLE = 'security_admin';
|
|
19
|
+
/** The role the platform puts on an ACL that has none (Explicit Roles). Any internal user has it. */
|
|
20
|
+
const AUTOMATIC_ROLE = 'snc_internal';
|
|
21
|
+
const BASE_FIELDS = 'name,type,type.name,operation,operation.name,active,admin_overrides,advanced,description,condition,script,sys_scope,sys_scope.scope,sys_updated_on';
|
|
22
|
+
const bool = (value) => value === 'true' || value === '1';
|
|
23
|
+
/**
|
|
24
|
+
* Access controls (sys_security_acl) and their roles, written through their forms in a named
|
|
25
|
+
* application and update set, each write verified by reading back its record and capture.
|
|
26
|
+
*
|
|
27
|
+
* Changing an ACL needs the elevated security_admin role on the writing session: construct the
|
|
28
|
+
* ServiceNowInstance with `elevatedRoles: ['security_admin']`. Reading ACLs needs no elevation,
|
|
29
|
+
* though a role the session may not read has no name (security_admin until elevated; nobody and
|
|
30
|
+
* maint always): its roleSysId identifies it.
|
|
31
|
+
*
|
|
32
|
+
* Creating an ACL with roles inserts it inactive, adds the roles, removes the snc_internal role
|
|
33
|
+
* the platform adds to an ACL that has none, then activates it: an ACL never stands active with
|
|
34
|
+
* fewer restrictions than asked for. Roles on an ACL are alternatives, so snc_internal left
|
|
35
|
+
* beside them would let every internal user pass.
|
|
36
|
+
*/
|
|
37
|
+
export class AclManager {
|
|
38
|
+
_instance;
|
|
39
|
+
_decisionType;
|
|
40
|
+
constructor(_instance) {
|
|
41
|
+
this._instance = _instance;
|
|
42
|
+
}
|
|
43
|
+
reader() {
|
|
44
|
+
return new MetadataReader(SessionManager.getInstance().getRequest(this._instance));
|
|
45
|
+
}
|
|
46
|
+
/** ACLs matching every given filter. At least one of table, name or scope is required. */
|
|
47
|
+
async list(options) {
|
|
48
|
+
const reader = this.reader();
|
|
49
|
+
const terms = [];
|
|
50
|
+
if (options.table !== undefined) {
|
|
51
|
+
if (!IDENT.test(options.table))
|
|
52
|
+
throw new AclError('invalid_input', 'table');
|
|
53
|
+
terms.push(`name=${options.table}^ORnameSTARTSWITH${options.table}.`);
|
|
54
|
+
}
|
|
55
|
+
if (options.name !== undefined) {
|
|
56
|
+
if (!RESOURCE.test(options.name) || SCRIPT.test(options.name))
|
|
57
|
+
throw new AclError('invalid_input', 'name');
|
|
58
|
+
terms.push(`name=${options.name}`);
|
|
59
|
+
}
|
|
60
|
+
if (options.scope !== undefined)
|
|
61
|
+
terms.push(`sys_scope=${(await resolveScope(reader, options.scope)).sysId}`);
|
|
62
|
+
if (!terms.length)
|
|
63
|
+
throw new AclError('filter_required');
|
|
64
|
+
if (options.operation !== undefined)
|
|
65
|
+
terms.push(`operation=${await this.lookup(reader, 'sys_security_operation', options.operation, 'operation_not_found')}`);
|
|
66
|
+
if (options.type !== undefined)
|
|
67
|
+
terms.push(`type=${await this.lookup(reader, 'sys_security_type', options.type, 'type_not_found')}`);
|
|
68
|
+
if (options.active !== undefined) {
|
|
69
|
+
if (typeof options.active !== 'boolean')
|
|
70
|
+
throw new AclError('invalid_input', 'active');
|
|
71
|
+
terms.push(`active=${options.active ? 'true' : 'false'}`);
|
|
72
|
+
}
|
|
73
|
+
const rows = await reader.rows(ACL, terms.join('^'), `sys_id,${await this.fields(reader)}`);
|
|
74
|
+
return this.records(reader, rows);
|
|
75
|
+
}
|
|
76
|
+
/** One ACL with its roles. */
|
|
77
|
+
async get(sysId) {
|
|
78
|
+
if (!ID.test(sysId ?? ''))
|
|
79
|
+
throw new AclError('invalid_input', 'sysId');
|
|
80
|
+
const reader = this.reader();
|
|
81
|
+
const row = await reader.exact(ACL, sysId, await this.fields(reader));
|
|
82
|
+
if (!row)
|
|
83
|
+
throw new AclError('acl_not_found');
|
|
84
|
+
return (await this.records(reader, [row]))[0];
|
|
85
|
+
}
|
|
86
|
+
async create(options) {
|
|
87
|
+
const reader = this.reader();
|
|
88
|
+
const type = options.type ?? 'record';
|
|
89
|
+
const typeId = await this.lookup(reader, 'sys_security_type', type, 'type_not_found');
|
|
90
|
+
const operationId = await this.lookup(reader, 'sys_security_operation', options.operation, 'operation_not_found');
|
|
91
|
+
const name = await this.aclName(reader, type, options);
|
|
92
|
+
const roles = await this.roles(reader, options.roles ?? []);
|
|
93
|
+
await this.requireElevation();
|
|
94
|
+
const fields = await this.fieldValues(reader, options);
|
|
95
|
+
const target = this.target(options);
|
|
96
|
+
const writer = this.writer();
|
|
97
|
+
const writes = [];
|
|
98
|
+
const active = options.active !== false;
|
|
99
|
+
// With roles, the ACL stays inactive until they are on it and the platform's own role is gone.
|
|
100
|
+
const staged = active && roles.length > 0;
|
|
101
|
+
const inserted = await writer.insert(ACL, { ...target, fields: { ...fields, type: typeId, operation: operationId, name,
|
|
102
|
+
active: active && !staged, admin_overrides: options.adminOverrides ?? true } });
|
|
103
|
+
writes.push(inserted);
|
|
104
|
+
const sysId = inserted.sysId;
|
|
105
|
+
try {
|
|
106
|
+
return await this.finishCreate(reader, writer, sysId, roles, staged, target, writes);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
// A refusal stays a refusal (callers recognise it by its brand), carrying the ACL it left behind.
|
|
110
|
+
if (isPolicyRefusal(error))
|
|
111
|
+
throw Object.assign(error, { aclSysId: sysId });
|
|
112
|
+
throw new AclPartialError(sysId, 'create', await this.state(sysId), error);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async finishCreate(reader, writer, sysId, roles, staged, target, writes) {
|
|
116
|
+
const automatic = await this.roleRows(reader, [sysId]);
|
|
117
|
+
const present = new Set(automatic.map(row => row.roleSysId));
|
|
118
|
+
for (const role of roles) {
|
|
119
|
+
if (present.has(role.sysId))
|
|
120
|
+
continue;
|
|
121
|
+
writes.push(await writer.insert(ACL_ROLE, { ...target, fields: { sys_security_acl: sysId, sys_user_role: role.sysId } }));
|
|
122
|
+
}
|
|
123
|
+
const removedAutomaticRoles = [];
|
|
124
|
+
if (roles.length) {
|
|
125
|
+
for (const row of automatic) {
|
|
126
|
+
if (roles.some(role => role.sysId === row.roleSysId))
|
|
127
|
+
continue;
|
|
128
|
+
writes.push(await writer.delete(ACL_ROLE, row.sysId, { ...target, confirm: { table: ACL_ROLE, sysId: row.sysId } }));
|
|
129
|
+
removedAutomaticRoles.push(row.role || row.roleSysId);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (roles.length) {
|
|
133
|
+
// The roles must be exactly those asked for before the ACL goes live: any other row would be one more way to pass.
|
|
134
|
+
const now = new Set((await this.roleRows(reader, [sysId])).map(row => row.roleSysId));
|
|
135
|
+
if (now.size !== roles.length || roles.some(role => !now.has(role.sysId)))
|
|
136
|
+
throw new AclError('roles_not_applied');
|
|
137
|
+
}
|
|
138
|
+
if (staged)
|
|
139
|
+
writes.push(await writer.update(ACL, sysId, { ...target, fields: { active: true } }));
|
|
140
|
+
const acl = await this.get(sysId);
|
|
141
|
+
return { acl, writes, removedAutomaticRoles, warnings: this.warnings(acl) };
|
|
142
|
+
}
|
|
143
|
+
async update(sysId, options) {
|
|
144
|
+
const previous = await this.get(sysId);
|
|
145
|
+
const reader = this.reader();
|
|
146
|
+
const fields = await this.fieldValues(reader, options);
|
|
147
|
+
if (options.operation !== undefined)
|
|
148
|
+
fields.operation = await this.lookup(reader, 'sys_security_operation', options.operation, 'operation_not_found');
|
|
149
|
+
if (options.adminOverrides !== undefined)
|
|
150
|
+
fields.admin_overrides = options.adminOverrides;
|
|
151
|
+
if (options.active !== undefined)
|
|
152
|
+
fields.active = options.active;
|
|
153
|
+
if (!Object.keys(fields).length)
|
|
154
|
+
throw new AclError('invalid_input', 'nothing_to_change');
|
|
155
|
+
await this.requireElevation();
|
|
156
|
+
const write = await this.writer().update(ACL, sysId, { ...this.target(options), fields });
|
|
157
|
+
const acl = await this.get(sysId);
|
|
158
|
+
return { acl, previous, writes: [write], removedAutomaticRoles: [], warnings: this.warnings(acl) };
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Deletes the ACL. The platform deletes its role rows with it (each captured as a DELETE). It offers Delete on an
|
|
162
|
+
* active record ACL only once it is inactive, so one is deactivated first, as a separate captured update.
|
|
163
|
+
*/
|
|
164
|
+
async delete(sysId, options) {
|
|
165
|
+
if (options?.confirm !== sysId)
|
|
166
|
+
throw new AclError('confirmation_required');
|
|
167
|
+
const previous = await this.get(sysId);
|
|
168
|
+
await this.requireElevation();
|
|
169
|
+
const writer = this.writer();
|
|
170
|
+
const target = this.target(options);
|
|
171
|
+
const writes = [];
|
|
172
|
+
const deactivate = previous.type === 'record' && previous.active;
|
|
173
|
+
try {
|
|
174
|
+
if (deactivate)
|
|
175
|
+
writes.push(await writer.update(ACL, sysId, { ...target, fields: { active: false } }));
|
|
176
|
+
writes.push(await writer.delete(ACL, sysId, { ...target, confirm: { table: ACL, sysId } }));
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
if (!deactivate)
|
|
180
|
+
throw error;
|
|
181
|
+
const before = await this.state(sysId);
|
|
182
|
+
// Refused before anything was written: the caller gets the writer's own error.
|
|
183
|
+
if (!writes.length && before === 'active')
|
|
184
|
+
throw error;
|
|
185
|
+
// Whatever failed after that (the deactivation's verification, the delete, a refusal, an unreadable state), a
|
|
186
|
+
// delete must not leave the ACL switched off: put the restriction back unless it is known active or gone.
|
|
187
|
+
if (before !== 'active' && before !== 'deleted') {
|
|
188
|
+
await writer.update(ACL, sysId, { ...target, fields: { active: true } }).catch(() => undefined);
|
|
189
|
+
}
|
|
190
|
+
const state = await this.state(sysId);
|
|
191
|
+
if (isPolicyRefusal(error))
|
|
192
|
+
throw Object.assign(error, { aclSysId: sysId, aclState: state });
|
|
193
|
+
throw new AclPartialError(sysId, 'delete', state, error);
|
|
194
|
+
}
|
|
195
|
+
return { previous, writes, removedAutomaticRoles: [], warnings: [] };
|
|
196
|
+
}
|
|
197
|
+
async addRole(sysId, role, target) {
|
|
198
|
+
const previous = await this.get(sysId);
|
|
199
|
+
const [resolved] = await this.roles(this.reader(), [role]);
|
|
200
|
+
if (previous.roles.some(row => row.roleSysId === resolved.sysId))
|
|
201
|
+
throw new AclError('role_already_present', resolved.name);
|
|
202
|
+
await this.requireSameScope(previous, target);
|
|
203
|
+
await this.requireElevation();
|
|
204
|
+
const write = await this.writer().insert(ACL_ROLE, { ...this.target(target),
|
|
205
|
+
fields: { sys_security_acl: sysId, sys_user_role: resolved.sysId } });
|
|
206
|
+
const acl = await this.get(sysId);
|
|
207
|
+
return { acl, previous, writes: [write], removedAutomaticRoles: [], warnings: this.warnings(acl) };
|
|
208
|
+
}
|
|
209
|
+
/** Removing the last role makes the platform add snc_internal back; the result warns when it did. */
|
|
210
|
+
async removeRole(sysId, role, target) {
|
|
211
|
+
const previous = await this.get(sysId);
|
|
212
|
+
const [resolved] = await this.roles(this.reader(), [role]);
|
|
213
|
+
const rows = previous.roles.filter(row => row.roleSysId === resolved.sysId);
|
|
214
|
+
if (!rows.length)
|
|
215
|
+
throw new AclError('role_not_present', resolved.name);
|
|
216
|
+
await this.requireSameScope(previous, target);
|
|
217
|
+
await this.requireElevation();
|
|
218
|
+
const writer = this.writer();
|
|
219
|
+
const writes = [];
|
|
220
|
+
for (const row of rows)
|
|
221
|
+
writes.push(await writer.delete(ACL_ROLE, row.sysId, { ...this.target(target), confirm: { table: ACL_ROLE, sysId: row.sysId } }));
|
|
222
|
+
const acl = await this.get(sysId);
|
|
223
|
+
const warnings = this.warnings(acl);
|
|
224
|
+
if (acl.roles.some(row => row.roleSysId === resolved.sysId)) {
|
|
225
|
+
warnings.unshift(`${resolved.name} is still on this ACL: the platform puts ${AUTOMATIC_ROLE} back on an ACL left without a role. Add the role it should have first.`);
|
|
226
|
+
}
|
|
227
|
+
else if (!previous.roles.some(row => row.role === AUTOMATIC_ROLE) && acl.roles.some(row => row.role === AUTOMATIC_ROLE)) {
|
|
228
|
+
warnings.unshift(`The platform added ${AUTOMATIC_ROLE} when the last role was removed: every internal user now passes this ACL.`);
|
|
229
|
+
}
|
|
230
|
+
return { acl, previous, writes, removedAutomaticRoles: [], warnings };
|
|
231
|
+
}
|
|
232
|
+
target(target) {
|
|
233
|
+
if (!target?.scope)
|
|
234
|
+
throw new AclError('invalid_input', 'scope');
|
|
235
|
+
if (target.updateSet !== undefined && !ID.test(target.updateSet))
|
|
236
|
+
throw new AclError('invalid_input', 'updateSet');
|
|
237
|
+
return { scope: target.scope, ...(target.updateSet ? { updateSet: target.updateSet } : {}),
|
|
238
|
+
...(target.storeCustomization ? { storeCustomization: target.storeCustomization } : {}) };
|
|
239
|
+
}
|
|
240
|
+
/** A writer allowed the access-control tables (the generic one refuses them). */
|
|
241
|
+
writer() {
|
|
242
|
+
const writer = new MetadataFormWriter(this._instance);
|
|
243
|
+
accessControlWriters.add(writer);
|
|
244
|
+
return writer;
|
|
245
|
+
}
|
|
246
|
+
/** The ACL read back after a failure. */
|
|
247
|
+
async state(sysId) {
|
|
248
|
+
try {
|
|
249
|
+
return (await this.get(sysId)).active ? 'active' : 'inactive';
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
return error instanceof AclError && error.code === 'acl_not_found' ? 'deleted' : 'unknown';
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/** A role row is written in the target application; it must be the ACL's own. */
|
|
256
|
+
async requireSameScope(acl, target) {
|
|
257
|
+
if (!target?.scope)
|
|
258
|
+
throw new AclError('invalid_input', 'scope');
|
|
259
|
+
if ((await resolveScope(this.reader(), target.scope)).sysId !== acl.scope)
|
|
260
|
+
throw new AclError('scope_mismatch');
|
|
261
|
+
}
|
|
262
|
+
async requireElevation() {
|
|
263
|
+
let elevated = [];
|
|
264
|
+
try {
|
|
265
|
+
elevated = (await new RoleElevation(this._instance).status()).elevated;
|
|
266
|
+
}
|
|
267
|
+
catch { /* unreadable: not elevated */ }
|
|
268
|
+
if (!elevated.includes(REQUIRED_ROLE))
|
|
269
|
+
throw new AclError('elevation_required', REQUIRED_ROLE);
|
|
270
|
+
}
|
|
271
|
+
/** decision_type exists from the release that added deny ACLs; read it only where it does. */
|
|
272
|
+
async fields(reader) {
|
|
273
|
+
// A failed read is not remembered: the next call asks again.
|
|
274
|
+
this._decisionType ??= reader.rows('sys_dictionary', `name=${ACL}^element=decision_type`, 'sys_id,element').then(rows => rows.length > 0, (error) => { this._decisionType = undefined; throw error; });
|
|
275
|
+
return `${BASE_FIELDS}${await this._decisionType ? ',decision_type' : ''}`;
|
|
276
|
+
}
|
|
277
|
+
async fieldValues(reader, options) {
|
|
278
|
+
const fields = {};
|
|
279
|
+
if (options.description !== undefined)
|
|
280
|
+
fields.description = options.description;
|
|
281
|
+
if (options.condition !== undefined)
|
|
282
|
+
fields.condition = options.condition;
|
|
283
|
+
if (options.script !== undefined)
|
|
284
|
+
Object.assign(fields, { advanced: true, script: options.script });
|
|
285
|
+
if (options.decisionType !== undefined) {
|
|
286
|
+
if (!['allow', 'deny'].includes(options.decisionType))
|
|
287
|
+
throw new AclError('invalid_input', 'decisionType');
|
|
288
|
+
await this.fields(reader);
|
|
289
|
+
if (!await this._decisionType)
|
|
290
|
+
throw new AclError('invalid_input', 'decisionType');
|
|
291
|
+
fields.decision_type = options.decisionType;
|
|
292
|
+
}
|
|
293
|
+
return fields;
|
|
294
|
+
}
|
|
295
|
+
async lookup(reader, table, name, missing) {
|
|
296
|
+
if (!IDENT.test(name ?? ''))
|
|
297
|
+
throw new AclError('invalid_input', missing === 'type_not_found' ? 'type' : 'operation');
|
|
298
|
+
const rows = await reader.rows(table, `name=${name}`, 'sys_id,name');
|
|
299
|
+
if (rows.length !== 1 || rows[0].name !== name)
|
|
300
|
+
throw new AclError(missing, name);
|
|
301
|
+
return rows[0].sys_id;
|
|
302
|
+
}
|
|
303
|
+
async aclName(reader, type, options) {
|
|
304
|
+
if (type !== 'record') {
|
|
305
|
+
if (options.table !== undefined || options.field !== undefined)
|
|
306
|
+
throw new AclError('invalid_input', 'table');
|
|
307
|
+
if (!RESOURCE.test(options.name ?? '') || SCRIPT.test(options.name ?? ''))
|
|
308
|
+
throw new AclError('invalid_input', 'name');
|
|
309
|
+
return options.name ?? '';
|
|
310
|
+
}
|
|
311
|
+
if (options.name !== undefined)
|
|
312
|
+
throw new AclError('invalid_input', 'name');
|
|
313
|
+
const table = options.table ?? '';
|
|
314
|
+
if (!IDENT.test(table))
|
|
315
|
+
throw new AclError('invalid_input', 'table');
|
|
316
|
+
const field = options.field;
|
|
317
|
+
if (field !== undefined && field !== '*' && !IDENT.test(field))
|
|
318
|
+
throw new AclError('invalid_input', 'field');
|
|
319
|
+
// The table and the tables it extends: a field may be defined on any of them.
|
|
320
|
+
const tables = [];
|
|
321
|
+
let next = table;
|
|
322
|
+
while (next && tables.length < 20) {
|
|
323
|
+
const rows = await reader.rows('sys_db_object', `name=${next}`, 'sys_id,name,super_class.name');
|
|
324
|
+
if (rows.length !== 1)
|
|
325
|
+
break;
|
|
326
|
+
tables.push(next);
|
|
327
|
+
next = rows[0]['super_class.name'] || undefined;
|
|
328
|
+
}
|
|
329
|
+
if (!tables.length)
|
|
330
|
+
throw new AclError('table_not_found', table);
|
|
331
|
+
if (field && field !== '*') {
|
|
332
|
+
const defined = await reader.rows('sys_dictionary', `nameIN${tables.join(',')}^element=${field}`, 'sys_id,element');
|
|
333
|
+
if (!defined.length)
|
|
334
|
+
throw new AclError('field_not_found', `${table}.${field}`);
|
|
335
|
+
}
|
|
336
|
+
return field ? `${table}.${field}` : table;
|
|
337
|
+
}
|
|
338
|
+
async roles(reader, names) {
|
|
339
|
+
const wanted = [...new Set(names.map(name => String(name).trim()).filter(Boolean))];
|
|
340
|
+
const invalid = wanted.find(name => !ROLE.test(name));
|
|
341
|
+
if (invalid !== undefined)
|
|
342
|
+
throw new AclError('invalid_input', 'role');
|
|
343
|
+
if (!wanted.length)
|
|
344
|
+
return [];
|
|
345
|
+
const rows = await reader.rows('sys_user_role', `nameIN${wanted.join(',')}`, 'sys_id,name');
|
|
346
|
+
return wanted.map(name => {
|
|
347
|
+
const matches = rows.filter(row => row.name === name);
|
|
348
|
+
// security_admin is only readable once elevated: the check runs on the elevated session for writes.
|
|
349
|
+
if (matches.length !== 1)
|
|
350
|
+
throw new AclError('role_not_found', name);
|
|
351
|
+
return { sysId: matches[0].sys_id, name };
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
async roleRows(reader, acls) {
|
|
355
|
+
if (!acls.length)
|
|
356
|
+
return [];
|
|
357
|
+
const rows = [];
|
|
358
|
+
// Bounded IN lists: an encoded query of thousands of sys_ids is refused by the instance.
|
|
359
|
+
for (let at = 0; at < acls.length; at += 100) {
|
|
360
|
+
// A role the session may not read (security_admin until elevated; nobody and maint always) has no name here.
|
|
361
|
+
const batch = await reader.rows(ACL_ROLE, `sys_security_aclIN${acls.slice(at, at + 100).join(',')}`, 'sys_id,sys_security_acl,sys_user_role,sys_user_role.name', ['sys_user_role.name']);
|
|
362
|
+
rows.push(...batch.map(row => ({ sysId: row.sys_id, roleSysId: row.sys_user_role, role: row['sys_user_role.name'], acl: row.sys_security_acl })));
|
|
363
|
+
}
|
|
364
|
+
return rows;
|
|
365
|
+
}
|
|
366
|
+
async records(reader, rows) {
|
|
367
|
+
const roles = await this.roleRows(reader, rows.map(row => row.sys_id));
|
|
368
|
+
return rows.map(row => ({
|
|
369
|
+
sysId: row.sys_id,
|
|
370
|
+
name: row.name,
|
|
371
|
+
type: row['type.name'] || row.type,
|
|
372
|
+
operation: row['operation.name'] || row.operation,
|
|
373
|
+
active: bool(row.active),
|
|
374
|
+
adminOverrides: bool(row.admin_overrides),
|
|
375
|
+
advanced: bool(row.advanced),
|
|
376
|
+
decisionType: row.decision_type ?? '',
|
|
377
|
+
description: row.description,
|
|
378
|
+
condition: row.condition,
|
|
379
|
+
script: row.script,
|
|
380
|
+
scope: row.sys_scope,
|
|
381
|
+
scopeName: row['sys_scope.scope'],
|
|
382
|
+
updatedOn: row.sys_updated_on,
|
|
383
|
+
roles: roles.filter(role => role.acl === row.sys_id).map(({ sysId, roleSysId, role }) => ({ sysId, roleSysId, role })),
|
|
384
|
+
}));
|
|
385
|
+
}
|
|
386
|
+
warnings(acl) {
|
|
387
|
+
const warnings = [];
|
|
388
|
+
if (acl.roles.length > 1 && acl.roles.some(role => role.role === AUTOMATIC_ROLE)) {
|
|
389
|
+
warnings.push(`${AUTOMATIC_ROLE} is one of this ACL's roles: any one role passes, so every internal user does.`);
|
|
390
|
+
}
|
|
391
|
+
const onlyAutomatic = acl.roles.length > 0 && acl.roles.every(role => role.role === AUTOMATIC_ROLE);
|
|
392
|
+
if (acl.active && (onlyAutomatic || !acl.roles.length) && !acl.condition && !(acl.advanced && acl.script.trim())) {
|
|
393
|
+
warnings.push(`This ACL has no role but ${AUTOMATIC_ROLE}, and no condition or script: every internal user passes it.`);
|
|
394
|
+
}
|
|
395
|
+
return warnings;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
//# sourceMappingURL=AclManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AclManager.js","sourceRoot":"","sources":["../../../src/sn/security/AclManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { MetadataScopeRef, MetadataWriteResult, StoreCustomizationOptions } from '../metadata/MetadataModels.js';
|
|
2
|
+
/** A role on an access control (a sys_security_acl_role row). */
|
|
3
|
+
export interface AclRole {
|
|
4
|
+
/** sys_id of the sys_security_acl_role row. */
|
|
5
|
+
sysId: string;
|
|
6
|
+
/** sys_user_role sys_id. */
|
|
7
|
+
roleSysId: string;
|
|
8
|
+
/** Role name; '' when the session may not read it: security_admin until elevated, nobody and maint always. */
|
|
9
|
+
role: string;
|
|
10
|
+
}
|
|
11
|
+
/** An access control as read back from the instance. */
|
|
12
|
+
export interface AclRecord {
|
|
13
|
+
sysId: string;
|
|
14
|
+
/** `table`, `table.field` or `table.*` for record ACLs; the resource name for other types. */
|
|
15
|
+
name: string;
|
|
16
|
+
/** sys_security_type name: record, ui_page, rest_endpoint, client_callable_script_include, … */
|
|
17
|
+
type: string;
|
|
18
|
+
/** sys_security_operation name: read, write, create, delete, execute, … */
|
|
19
|
+
operation: string;
|
|
20
|
+
active: boolean;
|
|
21
|
+
adminOverrides: boolean;
|
|
22
|
+
/** The script runs only when advanced is true. */
|
|
23
|
+
advanced: boolean;
|
|
24
|
+
/** allow or deny; '' on a release without decision types. */
|
|
25
|
+
decisionType: string;
|
|
26
|
+
description: string;
|
|
27
|
+
condition: string;
|
|
28
|
+
script: string;
|
|
29
|
+
/** sys_scope sys_id, and its scope name. */
|
|
30
|
+
scope: string;
|
|
31
|
+
scopeName: string;
|
|
32
|
+
updatedOn: string;
|
|
33
|
+
roles: AclRole[];
|
|
34
|
+
}
|
|
35
|
+
export interface AclListOptions {
|
|
36
|
+
/** ACLs of this table: the table itself and its fields (`table`, `table.*`, `table.<field>`). */
|
|
37
|
+
table?: string;
|
|
38
|
+
/** Exact ACL name. */
|
|
39
|
+
name?: string;
|
|
40
|
+
/** Only this application's ACLs: 'global', a scope name or a sys_scope sys_id. */
|
|
41
|
+
scope?: MetadataScopeRef;
|
|
42
|
+
operation?: string;
|
|
43
|
+
type?: string;
|
|
44
|
+
active?: boolean;
|
|
45
|
+
}
|
|
46
|
+
/** Where a write goes: the application, and the in-progress update set that captures it. */
|
|
47
|
+
export interface AclWriteTarget {
|
|
48
|
+
/** The ACL's application. */
|
|
49
|
+
scope: MetadataScopeRef;
|
|
50
|
+
/** In progress set of that application. The captures follow it; it need not be the user's current set. */
|
|
51
|
+
updateSet?: string;
|
|
52
|
+
/** Required when the application is an installed Store application (together with updateSet). */
|
|
53
|
+
storeCustomization?: StoreCustomizationOptions;
|
|
54
|
+
}
|
|
55
|
+
export interface AclCreateOptions extends AclWriteTarget {
|
|
56
|
+
/** sys_security_type name. Default record. */
|
|
57
|
+
type?: string;
|
|
58
|
+
/** sys_security_operation name, e.g. read, write, create, delete. */
|
|
59
|
+
operation: string;
|
|
60
|
+
/** record ACLs: the table, and optionally a field or '*' for every field. */
|
|
61
|
+
table?: string;
|
|
62
|
+
field?: string;
|
|
63
|
+
/** Other types: the resource name (UI page, REST endpoint, script include, …). */
|
|
64
|
+
name?: string;
|
|
65
|
+
/** Role names. Any one of them passes the ACL. */
|
|
66
|
+
roles?: string[];
|
|
67
|
+
condition?: string;
|
|
68
|
+
/** Script that sets `answer`; sets advanced, which the script needs to run. */
|
|
69
|
+
script?: string;
|
|
70
|
+
/** Default true, as on the form. */
|
|
71
|
+
adminOverrides?: boolean;
|
|
72
|
+
/** Default true. */
|
|
73
|
+
active?: boolean;
|
|
74
|
+
/** allow (default on the form) or deny. */
|
|
75
|
+
decisionType?: string;
|
|
76
|
+
description?: string;
|
|
77
|
+
}
|
|
78
|
+
export interface AclUpdateOptions extends AclWriteTarget {
|
|
79
|
+
operation?: string;
|
|
80
|
+
condition?: string;
|
|
81
|
+
script?: string;
|
|
82
|
+
adminOverrides?: boolean;
|
|
83
|
+
active?: boolean;
|
|
84
|
+
decisionType?: string;
|
|
85
|
+
description?: string;
|
|
86
|
+
}
|
|
87
|
+
export interface AclDeleteOptions extends AclWriteTarget {
|
|
88
|
+
/** Must repeat the ACL's sys_id. */
|
|
89
|
+
confirm: string;
|
|
90
|
+
}
|
|
91
|
+
export interface AclWriteResult {
|
|
92
|
+
/** The ACL as read back after the change; absent after a delete. */
|
|
93
|
+
acl?: AclRecord;
|
|
94
|
+
/** The ACL before the change; absent after a create. */
|
|
95
|
+
previous?: AclRecord;
|
|
96
|
+
/** Every verified write, in order (the ACL, its role rows). */
|
|
97
|
+
writes: MetadataWriteResult[];
|
|
98
|
+
/** Roles the platform added on its own that the write removed (snc_internal on a new ACL that was given roles). */
|
|
99
|
+
removedAutomaticRoles: string[];
|
|
100
|
+
/** Things to look at: e.g. snc_internal left beside other roles, which lets every internal user pass. */
|
|
101
|
+
warnings: string[];
|
|
102
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AclModels.js","sourceRoot":"","sources":["../../../src/sn/security/AclModels.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ElevationStatus } from '../../auth/SessionElevation.js';
|
|
2
|
+
import type { ServiceNowInstance } from '../ServiceNowInstance.js';
|
|
3
|
+
/**
|
|
4
|
+
* Elevation state of the session SessionManager shares for an instance: the one the metadata
|
|
5
|
+
* writers, AclManager and most managers use.
|
|
6
|
+
*
|
|
7
|
+
* To elevate, construct the ServiceNowInstance with `elevatedRoles`: every session then elevates
|
|
8
|
+
* as it logs in. Elevation is per server session, so elevating one session at runtime would leave
|
|
9
|
+
* any other session of the process (and any renewed session) without it.
|
|
10
|
+
*/
|
|
11
|
+
export declare class RoleElevation {
|
|
12
|
+
private readonly _instance;
|
|
13
|
+
constructor(_instance: ServiceNowInstance);
|
|
14
|
+
/** The roles the user may elevate to, and which of them the shared session has elevated. */
|
|
15
|
+
status(): Promise<ElevationStatus>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SessionManager } from '../../comm/http/SessionManager.js';
|
|
2
|
+
import { readElevation } from '../../auth/SessionElevation.js';
|
|
3
|
+
/**
|
|
4
|
+
* Elevation state of the session SessionManager shares for an instance: the one the metadata
|
|
5
|
+
* writers, AclManager and most managers use.
|
|
6
|
+
*
|
|
7
|
+
* To elevate, construct the ServiceNowInstance with `elevatedRoles`: every session then elevates
|
|
8
|
+
* as it logs in. Elevation is per server session, so elevating one session at runtime would leave
|
|
9
|
+
* any other session of the process (and any renewed session) without it.
|
|
10
|
+
*/
|
|
11
|
+
export class RoleElevation {
|
|
12
|
+
_instance;
|
|
13
|
+
constructor(_instance) {
|
|
14
|
+
this._instance = _instance;
|
|
15
|
+
}
|
|
16
|
+
/** The roles the user may elevate to, and which of them the shared session has elevated. */
|
|
17
|
+
async status() {
|
|
18
|
+
const request = await SessionManager.getInstance().getAuthenticatedRequest(this._instance);
|
|
19
|
+
return readElevation(await request.getUserSession());
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=RoleElevation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RoleElevation.js","sourceRoot":"","sources":["../../../src/sn/security/RoleElevation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAmB,MAAM,6BAA6B,CAAC;AAG7E;;;;;;;GAOG;AACH,MAAM,OAAO,aAAa;IACc;IAApC,YAAoC,SAA6B;QAA7B,cAAS,GAAT,SAAS,CAAoB;IAAG,CAAC;IAErE,4FAA4F;IACrF,KAAK,CAAC,MAAM;QACf,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,WAAW,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3F,OAAO,aAAa,CAAC,MAAM,OAAO,CAAC,cAAc,EAAiB,CAAC,CAAC;IACxE,CAAC;CACJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sonisoft/now-sdk-ext-core",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.18.1",
|
|
4
4
|
"description": "Comprehensive TypeScript library extending ServiceNow SDK with application management, ATF testing, real-time log monitoring, AMB event subscriptions, and automation tools",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"servicenow",
|