auth0-deploy-cli 8.23.2 → 8.24.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/CHANGELOG.md +11 -1
- package/lib/context/directory/handlers/index.js +2 -0
- package/lib/context/directory/handlers/riskAssessment.d.ts +6 -0
- package/lib/context/directory/handlers/riskAssessment.js +40 -0
- package/lib/context/yaml/handlers/index.js +2 -0
- package/lib/context/yaml/handlers/riskAssessment.d.ts +6 -0
- package/lib/context/yaml/handlers/riskAssessment.js +23 -0
- package/lib/tools/auth0/handlers/connections.d.ts +56 -1
- package/lib/tools/auth0/handlers/connections.js +194 -2
- package/lib/tools/auth0/handlers/index.js +2 -0
- package/lib/tools/auth0/handlers/riskAssessment.d.ts +39 -0
- package/lib/tools/auth0/handlers/riskAssessment.js +95 -0
- package/lib/tools/auth0/handlers/scimHandler.js +2 -0
- package/lib/tools/constants.d.ts +1 -0
- package/lib/tools/constants.js +1 -0
- package/lib/types.d.ts +3 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [8.24.0] - 2025-12-22
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add support for managing `riskAssessment` settings. [#1217]
|
|
15
|
+
- Add directory provisioning support for `google-apps` connections. [#1246]
|
|
16
|
+
|
|
10
17
|
## [8.23.2] - 2025-12-18
|
|
11
18
|
|
|
12
19
|
### Fixed
|
|
@@ -1575,6 +1582,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1575
1582
|
[#1211]: https://github.com/auth0/auth0-deploy-cli/issues/1211
|
|
1576
1583
|
[#1212]: https://github.com/auth0/auth0-deploy-cli/issues/1212
|
|
1577
1584
|
[#1214]: https://github.com/auth0/auth0-deploy-cli/issues/1214
|
|
1585
|
+
[#1217]: https://github.com/auth0/auth0-deploy-cli/issues/1217
|
|
1578
1586
|
[#1221]: https://github.com/auth0/auth0-deploy-cli/issues/1221
|
|
1579
1587
|
[#1223]: https://github.com/auth0/auth0-deploy-cli/issues/1223
|
|
1580
1588
|
[#1224]: https://github.com/auth0/auth0-deploy-cli/issues/1224
|
|
@@ -1584,7 +1592,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1584
1592
|
[#1239]: https://github.com/auth0/auth0-deploy-cli/issues/1239
|
|
1585
1593
|
[#1240]: https://github.com/auth0/auth0-deploy-cli/issues/1240
|
|
1586
1594
|
[#1244]: https://github.com/auth0/auth0-deploy-cli/issues/1244
|
|
1587
|
-
[
|
|
1595
|
+
[#1246]: https://github.com/auth0/auth0-deploy-cli/issues/1246
|
|
1596
|
+
[Unreleased]: https://github.com/auth0/auth0-deploy-cli/compare/v8.24.0...HEAD
|
|
1597
|
+
[8.24.0]: https://github.com/auth0/auth0-deploy-cli/compare/v8.23.2...v8.24.0
|
|
1588
1598
|
[8.23.2]: https://github.com/auth0/auth0-deploy-cli/compare/v8.23.1...v8.23.2
|
|
1589
1599
|
[8.23.1]: https://github.com/auth0/auth0-deploy-cli/compare/v8.23.0...v8.23.1
|
|
1590
1600
|
[8.23.0]: https://github.com/auth0/auth0-deploy-cli/compare/v8.22.0...v8.23.0
|
|
@@ -23,6 +23,7 @@ const actions_1 = __importDefault(require("./actions"));
|
|
|
23
23
|
const organizations_1 = __importDefault(require("./organizations"));
|
|
24
24
|
const triggers_1 = __importDefault(require("./triggers"));
|
|
25
25
|
const attackProtection_1 = __importDefault(require("./attackProtection"));
|
|
26
|
+
const riskAssessment_1 = __importDefault(require("./riskAssessment"));
|
|
26
27
|
const branding_1 = __importDefault(require("./branding"));
|
|
27
28
|
const phoneProvider_1 = __importDefault(require("./phoneProvider"));
|
|
28
29
|
const phoneTemplates_1 = __importDefault(require("./phoneTemplates"));
|
|
@@ -65,6 +66,7 @@ const directoryHandlers = {
|
|
|
65
66
|
organizations: organizations_1.default,
|
|
66
67
|
triggers: triggers_1.default,
|
|
67
68
|
attackProtection: attackProtection_1.default,
|
|
69
|
+
riskAssessment: riskAssessment_1.default,
|
|
68
70
|
branding: branding_1.default,
|
|
69
71
|
phoneProviders: phoneProvider_1.default,
|
|
70
72
|
phoneTemplates: phoneTemplates_1.default,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DirectoryHandler } from '.';
|
|
2
|
+
import { ParsedAsset } from '../../../types';
|
|
3
|
+
import { RiskAssessment } from '../../../tools/auth0/handlers/riskAssessment';
|
|
4
|
+
type ParsedRiskAssessment = ParsedAsset<'riskAssessment', RiskAssessment>;
|
|
5
|
+
declare const riskAssessmentHandler: DirectoryHandler<ParsedRiskAssessment>;
|
|
6
|
+
export default riskAssessmentHandler;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const tools_1 = require("../../../tools");
|
|
9
|
+
const utils_1 = require("../../../utils");
|
|
10
|
+
function parse(context) {
|
|
11
|
+
const riskAssessmentDirectory = path_1.default.join(context.filePath, tools_1.constants.RISK_ASSESSMENT_DIRECTORY);
|
|
12
|
+
const riskAssessmentFile = path_1.default.join(riskAssessmentDirectory, 'settings.json');
|
|
13
|
+
if (!(0, utils_1.existsMustBeDir)(riskAssessmentDirectory)) {
|
|
14
|
+
return { riskAssessment: null };
|
|
15
|
+
}
|
|
16
|
+
if (!(0, utils_1.isFile)(riskAssessmentFile)) {
|
|
17
|
+
return { riskAssessment: null };
|
|
18
|
+
}
|
|
19
|
+
const riskAssessment = (0, utils_1.loadJSON)(riskAssessmentFile, {
|
|
20
|
+
mappings: context.mappings,
|
|
21
|
+
disableKeywordReplacement: context.disableKeywordReplacement,
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
riskAssessment,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async function dump(context) {
|
|
28
|
+
const { riskAssessment } = context.assets;
|
|
29
|
+
if (!riskAssessment)
|
|
30
|
+
return;
|
|
31
|
+
const riskAssessmentDirectory = path_1.default.join(context.filePath, tools_1.constants.RISK_ASSESSMENT_DIRECTORY);
|
|
32
|
+
const riskAssessmentFile = path_1.default.join(riskAssessmentDirectory, 'settings.json');
|
|
33
|
+
fs_extra_1.default.ensureDirSync(riskAssessmentDirectory);
|
|
34
|
+
(0, utils_1.dumpJSON)(riskAssessmentFile, riskAssessment);
|
|
35
|
+
}
|
|
36
|
+
const riskAssessmentHandler = {
|
|
37
|
+
parse,
|
|
38
|
+
dump,
|
|
39
|
+
};
|
|
40
|
+
exports.default = riskAssessmentHandler;
|
|
@@ -23,6 +23,7 @@ const organizations_1 = __importDefault(require("./organizations"));
|
|
|
23
23
|
const actions_1 = __importDefault(require("./actions"));
|
|
24
24
|
const triggers_1 = __importDefault(require("./triggers"));
|
|
25
25
|
const attackProtection_1 = __importDefault(require("./attackProtection"));
|
|
26
|
+
const riskAssessment_1 = __importDefault(require("./riskAssessment"));
|
|
26
27
|
const branding_1 = __importDefault(require("./branding"));
|
|
27
28
|
const phoneProvider_1 = __importDefault(require("./phoneProvider"));
|
|
28
29
|
const phoneTemplates_1 = __importDefault(require("./phoneTemplates"));
|
|
@@ -65,6 +66,7 @@ const yamlHandlers = {
|
|
|
65
66
|
organizations: organizations_1.default,
|
|
66
67
|
triggers: triggers_1.default,
|
|
67
68
|
attackProtection: attackProtection_1.default,
|
|
69
|
+
riskAssessment: riskAssessment_1.default,
|
|
68
70
|
branding: branding_1.default,
|
|
69
71
|
phoneProviders: phoneProvider_1.default,
|
|
70
72
|
phoneTemplates: phoneTemplates_1.default,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { YAMLHandler } from '.';
|
|
2
|
+
import { RiskAssessment } from '../../../tools/auth0/handlers/riskAssessment';
|
|
3
|
+
import { ParsedAsset } from '../../../types';
|
|
4
|
+
type ParsedRiskAssessment = ParsedAsset<'riskAssessment', RiskAssessment>;
|
|
5
|
+
declare const riskAssessmentHandler: YAMLHandler<ParsedRiskAssessment>;
|
|
6
|
+
export default riskAssessmentHandler;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
async function parse(context) {
|
|
4
|
+
const { riskAssessment } = context.assets;
|
|
5
|
+
if (!riskAssessment)
|
|
6
|
+
return { riskAssessment: null };
|
|
7
|
+
return {
|
|
8
|
+
riskAssessment,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
async function dump(context) {
|
|
12
|
+
const { riskAssessment } = context.assets;
|
|
13
|
+
if (!riskAssessment)
|
|
14
|
+
return { riskAssessment: null };
|
|
15
|
+
return {
|
|
16
|
+
riskAssessment,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const riskAssessmentHandler = {
|
|
20
|
+
parse,
|
|
21
|
+
dump,
|
|
22
|
+
};
|
|
23
|
+
exports.default = riskAssessmentHandler;
|
|
@@ -78,11 +78,40 @@ export declare const schema: {
|
|
|
78
78
|
required: string[];
|
|
79
79
|
additionalProperties: boolean;
|
|
80
80
|
};
|
|
81
|
+
directory_provisioning_configuration: {
|
|
82
|
+
type: string;
|
|
83
|
+
properties: {
|
|
84
|
+
mapping: {
|
|
85
|
+
type: string;
|
|
86
|
+
items: {
|
|
87
|
+
type: string;
|
|
88
|
+
properties: {
|
|
89
|
+
auth0: {
|
|
90
|
+
type: string;
|
|
91
|
+
description: string;
|
|
92
|
+
};
|
|
93
|
+
idp: {
|
|
94
|
+
type: string;
|
|
95
|
+
description: string;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
synchronize_automatically: {
|
|
101
|
+
type: string;
|
|
102
|
+
description: string;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
};
|
|
81
106
|
};
|
|
82
107
|
required: string[];
|
|
83
108
|
};
|
|
84
109
|
};
|
|
85
|
-
|
|
110
|
+
type DirectoryProvisioningConfig = Management.GetDirectoryProvisioningResponseContent;
|
|
111
|
+
export type Connection = Management.ConnectionForList & {
|
|
112
|
+
enabled_clients?: string[];
|
|
113
|
+
directory_provisioning_configuration?: DirectoryProvisioningConfig;
|
|
114
|
+
};
|
|
86
115
|
export declare const addExcludedConnectionPropertiesToChanges: ({ proposedChanges, existingConnections, config, }: {
|
|
87
116
|
proposedChanges: CalculatedChanges;
|
|
88
117
|
existingConnections: Asset[];
|
|
@@ -135,7 +164,33 @@ export default class ConnectionsHandler extends DefaultAPIHandler {
|
|
|
135
164
|
} | {
|
|
136
165
|
options?: undefined;
|
|
137
166
|
};
|
|
167
|
+
/**
|
|
168
|
+
* Retrieves directory provisioning configuration for a specific Auth0 connection.
|
|
169
|
+
* @param connectionId - The unique identifier of the connection
|
|
170
|
+
* @returns A promise that resolves to the configuration object, or null if not configured/supported
|
|
171
|
+
*/
|
|
172
|
+
getConnectionDirectoryProvisioning(connectionId: string): Promise<DirectoryProvisioningConfig | null>;
|
|
173
|
+
/**
|
|
174
|
+
* Creates directory provisioning configuration for a connection.
|
|
175
|
+
*/
|
|
176
|
+
private createConnectionDirectoryProvisioning;
|
|
177
|
+
/**
|
|
178
|
+
* Updates directory provisioning configuration for a connection.
|
|
179
|
+
*/
|
|
180
|
+
private updateConnectionDirectoryProvisioning;
|
|
181
|
+
/**
|
|
182
|
+
* Deletes directory provisioning configuration for a connection.
|
|
183
|
+
*/
|
|
184
|
+
private deleteConnectionDirectoryProvisioning;
|
|
185
|
+
/**
|
|
186
|
+
* This function processes directory provisioning for create, update, and conflict operations.
|
|
187
|
+
* Directory provisioning is only supported for google-apps strategy connections.
|
|
188
|
+
*
|
|
189
|
+
* @param changes - Object containing arrays of connections to create, update, and resolve conflicts for
|
|
190
|
+
*/
|
|
191
|
+
processConnectionDirectoryProvisioning(changes: CalculatedChanges): Promise<void>;
|
|
138
192
|
getType(): Promise<Asset[] | null>;
|
|
139
193
|
calcChanges(assets: Assets): Promise<CalculatedChanges>;
|
|
140
194
|
processChanges(assets: Assets): Promise<void>;
|
|
141
195
|
}
|
|
196
|
+
export {};
|
|
@@ -93,6 +93,25 @@ exports.schema = {
|
|
|
93
93
|
required: ['active'],
|
|
94
94
|
additionalProperties: false,
|
|
95
95
|
},
|
|
96
|
+
directory_provisioning_configuration: {
|
|
97
|
+
type: 'object',
|
|
98
|
+
properties: {
|
|
99
|
+
mapping: {
|
|
100
|
+
type: 'array',
|
|
101
|
+
items: {
|
|
102
|
+
type: 'object',
|
|
103
|
+
properties: {
|
|
104
|
+
auth0: { type: 'string', description: 'The field location in the Auth0 schema' },
|
|
105
|
+
idp: { type: 'string', description: 'The field location in the IDP schema' },
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
synchronize_automatically: {
|
|
110
|
+
type: 'boolean',
|
|
111
|
+
description: 'The field whether periodic automatic synchronization is enabled',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
96
115
|
},
|
|
97
116
|
required: ['name', 'strategy'],
|
|
98
117
|
},
|
|
@@ -286,6 +305,169 @@ class ConnectionsHandler extends default_1.default {
|
|
|
286
305
|
return {};
|
|
287
306
|
}
|
|
288
307
|
}
|
|
308
|
+
/**
|
|
309
|
+
* Retrieves directory provisioning configuration for a specific Auth0 connection.
|
|
310
|
+
* @param connectionId - The unique identifier of the connection
|
|
311
|
+
* @returns A promise that resolves to the configuration object, or null if not configured/supported
|
|
312
|
+
*/
|
|
313
|
+
async getConnectionDirectoryProvisioning(connectionId) {
|
|
314
|
+
if (!connectionId)
|
|
315
|
+
return null;
|
|
316
|
+
const creates = [connectionId];
|
|
317
|
+
let config = null;
|
|
318
|
+
try {
|
|
319
|
+
await this.client.pool
|
|
320
|
+
.addEachTask({
|
|
321
|
+
data: creates || [],
|
|
322
|
+
generator: async (id) => this.client.connections.directoryProvisioning
|
|
323
|
+
.get(id)
|
|
324
|
+
.then((resp) => {
|
|
325
|
+
config = resp;
|
|
326
|
+
})
|
|
327
|
+
.catch((err) => {
|
|
328
|
+
throw new auth0_1.ManagementError(err);
|
|
329
|
+
}),
|
|
330
|
+
})
|
|
331
|
+
.promise();
|
|
332
|
+
const stripKeysFromOutput = [
|
|
333
|
+
'connection_id',
|
|
334
|
+
'connection_name',
|
|
335
|
+
'strategy',
|
|
336
|
+
'created_at',
|
|
337
|
+
'updated_at',
|
|
338
|
+
];
|
|
339
|
+
stripKeysFromOutput.forEach((key) => {
|
|
340
|
+
if (config && key in config) {
|
|
341
|
+
delete config[key];
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
return config;
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
const errLog = `Unable to fetch directory provisioning for connection '${connectionId}'. `;
|
|
348
|
+
if (error instanceof auth0_1.ManagementError) {
|
|
349
|
+
const bodyMessage = error.body?.message;
|
|
350
|
+
logger_1.default.warn(errLog + bodyMessage);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
logger_1.default.error(errLog, error?.message);
|
|
354
|
+
}
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Creates directory provisioning configuration for a connection.
|
|
360
|
+
*/
|
|
361
|
+
async createConnectionDirectoryProvisioning(connectionId, payload) {
|
|
362
|
+
if (!connectionId) {
|
|
363
|
+
throw new Error('Connection ID is required to create directory provisioning configuration.');
|
|
364
|
+
}
|
|
365
|
+
const createPayload = {
|
|
366
|
+
mapping: payload.mapping,
|
|
367
|
+
synchronize_automatically: payload.synchronize_automatically,
|
|
368
|
+
};
|
|
369
|
+
await this.client.connections.directoryProvisioning.create(connectionId, createPayload);
|
|
370
|
+
logger_1.default.debug(`Created directory provisioning for connection '${connectionId}'`);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Updates directory provisioning configuration for a connection.
|
|
374
|
+
*/
|
|
375
|
+
async updateConnectionDirectoryProvisioning(connectionId, payload) {
|
|
376
|
+
if (!connectionId) {
|
|
377
|
+
throw new Error('Connection ID is required to update directory provisioning configuration.');
|
|
378
|
+
}
|
|
379
|
+
const updatePayload = {
|
|
380
|
+
mapping: payload.mapping,
|
|
381
|
+
synchronize_automatically: payload.synchronize_automatically,
|
|
382
|
+
};
|
|
383
|
+
await this.client.connections.directoryProvisioning.update(connectionId, updatePayload);
|
|
384
|
+
logger_1.default.debug(`Updated directory provisioning for connection '${connectionId}'`);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Deletes directory provisioning configuration for a connection.
|
|
388
|
+
*/
|
|
389
|
+
async deleteConnectionDirectoryProvisioning(connectionId) {
|
|
390
|
+
if (!connectionId) {
|
|
391
|
+
throw new Error('Connection ID is required to delete directory provisioning configuration.');
|
|
392
|
+
}
|
|
393
|
+
await this.client.connections.directoryProvisioning.delete(connectionId);
|
|
394
|
+
logger_1.default.debug(`Deleted directory provisioning for connection '${connectionId}'`);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* This function processes directory provisioning for create, update, and conflict operations.
|
|
398
|
+
* Directory provisioning is only supported for google-apps strategy connections.
|
|
399
|
+
*
|
|
400
|
+
* @param changes - Object containing arrays of connections to create, update, and resolve conflicts for
|
|
401
|
+
*/
|
|
402
|
+
async processConnectionDirectoryProvisioning(changes) {
|
|
403
|
+
const { create, update, conflicts } = changes;
|
|
404
|
+
// Build a map of existing connections by ID for quick lookup
|
|
405
|
+
const existingConnectionsMap = (0, lodash_1.keyBy)(this.existing || [], 'id');
|
|
406
|
+
// Filter to only google-apps connections
|
|
407
|
+
const googleAppsWithDirProvFilter = (conn) => conn.strategy === 'google-apps';
|
|
408
|
+
const connectionsToProcess = [
|
|
409
|
+
...update.filter(googleAppsWithDirProvFilter),
|
|
410
|
+
...create.filter(googleAppsWithDirProvFilter),
|
|
411
|
+
...conflicts.filter(googleAppsWithDirProvFilter),
|
|
412
|
+
];
|
|
413
|
+
if (connectionsToProcess.length === 0) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
const directoryConnectionsToUpdate = [];
|
|
417
|
+
const directoryConnectionsToCreate = [];
|
|
418
|
+
const directoryConnectionsToDelete = [];
|
|
419
|
+
for (const conn of connectionsToProcess) {
|
|
420
|
+
if (!conn.id)
|
|
421
|
+
continue;
|
|
422
|
+
const existingConn = existingConnectionsMap[conn.id];
|
|
423
|
+
const existingConfig = existingConn?.directory_provisioning_configuration;
|
|
424
|
+
const proposedConfig = conn.directory_provisioning_configuration;
|
|
425
|
+
if (existingConfig && proposedConfig) {
|
|
426
|
+
directoryConnectionsToUpdate.push(conn);
|
|
427
|
+
}
|
|
428
|
+
else if (!existingConfig && proposedConfig) {
|
|
429
|
+
directoryConnectionsToCreate.push(conn);
|
|
430
|
+
}
|
|
431
|
+
else if (existingConfig && !proposedConfig) {
|
|
432
|
+
directoryConnectionsToDelete.push(conn);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
// Process updates first
|
|
436
|
+
await this.client.pool
|
|
437
|
+
.addEachTask({
|
|
438
|
+
data: directoryConnectionsToUpdate || [],
|
|
439
|
+
generator: (conn) => this.updateConnectionDirectoryProvisioning(conn.id, conn.directory_provisioning_configuration).catch((err) => {
|
|
440
|
+
throw new Error(`Failed to update directory provisioning for connection '${conn.id}':\n${err}`);
|
|
441
|
+
}),
|
|
442
|
+
})
|
|
443
|
+
.promise();
|
|
444
|
+
// Process creates
|
|
445
|
+
await this.client.pool
|
|
446
|
+
.addEachTask({
|
|
447
|
+
data: directoryConnectionsToCreate || [],
|
|
448
|
+
generator: (conn) => this.createConnectionDirectoryProvisioning(conn.id, conn.directory_provisioning_configuration).catch((err) => {
|
|
449
|
+
throw new Error(`Failed to create directory provisioning for connection '${conn.id}':\n${err}`);
|
|
450
|
+
}),
|
|
451
|
+
})
|
|
452
|
+
.promise();
|
|
453
|
+
// Process deletes
|
|
454
|
+
if (this.config('AUTH0_ALLOW_DELETE') === 'true' ||
|
|
455
|
+
this.config('AUTH0_ALLOW_DELETE') === true) {
|
|
456
|
+
await this.client.pool
|
|
457
|
+
.addEachTask({
|
|
458
|
+
data: directoryConnectionsToDelete || [],
|
|
459
|
+
generator: (conn) => this.deleteConnectionDirectoryProvisioning(conn.id).catch((err) => {
|
|
460
|
+
throw new Error(`Failed to delete directory provisioning for connection '${conn.id}':\n${err}`);
|
|
461
|
+
}),
|
|
462
|
+
})
|
|
463
|
+
.promise();
|
|
464
|
+
}
|
|
465
|
+
else if (directoryConnectionsToDelete.length) {
|
|
466
|
+
logger_1.default.warn(`Detected directory provisioning configs to delete. Deletes are disabled (set 'AUTH0_ALLOW_DELETE' to true to allow).\n${directoryConnectionsToDelete
|
|
467
|
+
.map((i) => this.objString(i))
|
|
468
|
+
.join('\n')}`);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
289
471
|
async getType() {
|
|
290
472
|
if (this.existing)
|
|
291
473
|
return this.existing;
|
|
@@ -306,10 +488,18 @@ class ConnectionsHandler extends default_1.default {
|
|
|
306
488
|
if (!con?.id)
|
|
307
489
|
return con;
|
|
308
490
|
const enabledClients = await (0, exports.getConnectionEnabledClients)(this.client, con.id);
|
|
491
|
+
// Cast to Asset to allow adding properties
|
|
492
|
+
let connection = { ...con };
|
|
309
493
|
if (enabledClients && enabledClients?.length) {
|
|
310
|
-
|
|
494
|
+
connection.enabled_clients = enabledClients;
|
|
495
|
+
}
|
|
496
|
+
if (connection.strategy === 'google-apps') {
|
|
497
|
+
const dirProvConfig = await this.getConnectionDirectoryProvisioning(con.id);
|
|
498
|
+
if (dirProvConfig) {
|
|
499
|
+
connection.directory_provisioning_configuration = dirProvConfig;
|
|
500
|
+
}
|
|
311
501
|
}
|
|
312
|
-
return
|
|
502
|
+
return connection;
|
|
313
503
|
}));
|
|
314
504
|
this.existing = connectionsWithEnabledClients;
|
|
315
505
|
// Apply `scim_configuration` to all the relevant `SCIM` connections. This method mutates `this.existing`.
|
|
@@ -366,6 +556,8 @@ class ConnectionsHandler extends default_1.default {
|
|
|
366
556
|
await super.processChanges(assets, (0, utils_1.filterExcluded)(changes, excludedConnections));
|
|
367
557
|
// process enabled clients
|
|
368
558
|
await (0, exports.processConnectionEnabledClients)(this.client, this.type, (0, utils_1.filterExcluded)(changes, excludedConnections));
|
|
559
|
+
// process directory provisioning
|
|
560
|
+
await this.processConnectionDirectoryProvisioning((0, utils_1.filterExcluded)(changes, excludedConnections));
|
|
369
561
|
}
|
|
370
562
|
}
|
|
371
563
|
exports.default = ConnectionsHandler;
|
|
@@ -60,6 +60,7 @@ const actions = __importStar(require("./actions"));
|
|
|
60
60
|
const triggers = __importStar(require("./triggers"));
|
|
61
61
|
const organizations = __importStar(require("./organizations"));
|
|
62
62
|
const attackProtection = __importStar(require("./attackProtection"));
|
|
63
|
+
const riskAssessment = __importStar(require("./riskAssessment"));
|
|
63
64
|
const logStreams = __importStar(require("./logStreams"));
|
|
64
65
|
const customDomains = __importStar(require("./customDomains"));
|
|
65
66
|
const themes = __importStar(require("./themes"));
|
|
@@ -100,6 +101,7 @@ const auth0ApiHandlers = {
|
|
|
100
101
|
triggers,
|
|
101
102
|
organizations,
|
|
102
103
|
attackProtection,
|
|
104
|
+
riskAssessment,
|
|
103
105
|
logStreams,
|
|
104
106
|
customDomains,
|
|
105
107
|
themes,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import DefaultAPIHandler from './default';
|
|
2
|
+
import { Assets } from '../../../types';
|
|
3
|
+
import { Management } from 'auth0';
|
|
4
|
+
export declare const schema: {
|
|
5
|
+
type: string;
|
|
6
|
+
properties: {
|
|
7
|
+
settings: {
|
|
8
|
+
type: string;
|
|
9
|
+
properties: {
|
|
10
|
+
enabled: {
|
|
11
|
+
type: string;
|
|
12
|
+
description: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
required: string[];
|
|
16
|
+
};
|
|
17
|
+
new_device: {
|
|
18
|
+
type: string;
|
|
19
|
+
properties: {
|
|
20
|
+
remember_for: {
|
|
21
|
+
type: string;
|
|
22
|
+
description: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
required: string[];
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
required: string[];
|
|
29
|
+
};
|
|
30
|
+
export type RiskAssessment = {
|
|
31
|
+
settings: Management.GetRiskAssessmentsSettingsResponseContent;
|
|
32
|
+
new_device?: Management.GetRiskAssessmentsSettingsNewDeviceResponseContent;
|
|
33
|
+
};
|
|
34
|
+
export default class RiskAssessmentHandler extends DefaultAPIHandler {
|
|
35
|
+
existing: RiskAssessment;
|
|
36
|
+
constructor(config: DefaultAPIHandler);
|
|
37
|
+
getType(): Promise<RiskAssessment>;
|
|
38
|
+
processChanges(assets: Assets): Promise<void>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.schema = void 0;
|
|
7
|
+
const default_1 = __importDefault(require("./default"));
|
|
8
|
+
const auth0_1 = require("auth0");
|
|
9
|
+
exports.schema = {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
settings: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
enabled: {
|
|
16
|
+
type: 'boolean',
|
|
17
|
+
description: 'Whether or not risk assessment is enabled.',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
required: ['enabled'],
|
|
21
|
+
},
|
|
22
|
+
new_device: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
remember_for: {
|
|
26
|
+
type: 'number',
|
|
27
|
+
description: 'Length of time to remember devices for, in days.',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
required: ['remember_for'],
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
required: ['settings'],
|
|
34
|
+
};
|
|
35
|
+
class RiskAssessmentHandler extends default_1.default {
|
|
36
|
+
constructor(config) {
|
|
37
|
+
super({
|
|
38
|
+
...config,
|
|
39
|
+
type: 'riskAssessment',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async getType() {
|
|
43
|
+
if (this.existing) {
|
|
44
|
+
return this.existing;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const [settings, newDeviceSettings] = await Promise.all([
|
|
48
|
+
this.client.riskAssessments.settings.get(),
|
|
49
|
+
this.client.riskAssessments.settings.newDevice.get().catch((err) => {
|
|
50
|
+
if (err instanceof auth0_1.ManagementError && err?.statusCode === 404) {
|
|
51
|
+
return { remember_for: 0 };
|
|
52
|
+
}
|
|
53
|
+
throw err;
|
|
54
|
+
}),
|
|
55
|
+
]);
|
|
56
|
+
const riskAssessment = {
|
|
57
|
+
settings: settings,
|
|
58
|
+
new_device: newDeviceSettings,
|
|
59
|
+
...(newDeviceSettings.remember_for > 0 && {
|
|
60
|
+
new_device: newDeviceSettings,
|
|
61
|
+
}),
|
|
62
|
+
};
|
|
63
|
+
this.existing = riskAssessment;
|
|
64
|
+
return this.existing;
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
if (err instanceof auth0_1.ManagementError && err.statusCode === 404) {
|
|
68
|
+
const riskAssessment = {
|
|
69
|
+
settings: { enabled: false },
|
|
70
|
+
};
|
|
71
|
+
this.existing = riskAssessment;
|
|
72
|
+
return this.existing;
|
|
73
|
+
}
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async processChanges(assets) {
|
|
78
|
+
const { riskAssessment } = assets;
|
|
79
|
+
// Non-existing section means it doesn't need to be processed
|
|
80
|
+
if (!riskAssessment) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const updates = [];
|
|
84
|
+
// Update main settings (enabled flag)
|
|
85
|
+
updates.push(this.client.riskAssessments.settings.update(riskAssessment?.settings));
|
|
86
|
+
// Update new device settings if provided
|
|
87
|
+
if (riskAssessment.new_device) {
|
|
88
|
+
updates.push(this.client.riskAssessments.settings.newDevice.update(riskAssessment.new_device));
|
|
89
|
+
}
|
|
90
|
+
await Promise.all(updates);
|
|
91
|
+
this.updated += 1;
|
|
92
|
+
this.didUpdate(riskAssessment);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.default = RiskAssessmentHandler;
|
|
@@ -190,6 +190,7 @@ class ScimHandler {
|
|
|
190
190
|
// Remove `scim_configuration` from `bodyParams`, because `connections.update` doesn't accept it.
|
|
191
191
|
const { scim_configuration: scimBodyParams } = bodyParams;
|
|
192
192
|
delete bodyParams.scim_configuration;
|
|
193
|
+
delete bodyParams.directory_provisioning_configuration;
|
|
193
194
|
// First, update `connections`.
|
|
194
195
|
const updated = await this.connectionsManager.update(requestParams.id, bodyParams);
|
|
195
196
|
const idMapEntry = this.idMap.get(requestParams.id);
|
|
@@ -223,6 +224,7 @@ class ScimHandler {
|
|
|
223
224
|
// Remove `scim_configuration` from `bodyParams`, because `connections.create` doesn't accept it.
|
|
224
225
|
const { scim_configuration: scimBodyParams } = bodyParams;
|
|
225
226
|
delete bodyParams.scim_configuration;
|
|
227
|
+
delete bodyParams.directory_provisioning_configuration;
|
|
226
228
|
// First, create the new `connection`.
|
|
227
229
|
const data = await this.connectionsManager.create(bodyParams);
|
|
228
230
|
if (data?.id && scimBodyParams && this.scimScopes.create) {
|
package/lib/tools/constants.d.ts
CHANGED
|
@@ -57,6 +57,7 @@ declare const constants: {
|
|
|
57
57
|
CONNECTIONS_ID_NAME: string;
|
|
58
58
|
ROLES_DIRECTORY: string;
|
|
59
59
|
ATTACK_PROTECTION_DIRECTORY: string;
|
|
60
|
+
RISK_ASSESSMENT_DIRECTORY: string;
|
|
60
61
|
GUARDIAN_FACTORS: string[];
|
|
61
62
|
GUARDIAN_POLICIES: string[];
|
|
62
63
|
GUARDIAN_PHONE_PROVIDERS: string[];
|
package/lib/tools/constants.js
CHANGED
package/lib/types.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { NetworkACL } from './tools/auth0/handlers/networkACLs';
|
|
|
18
18
|
import { UserAttributeProfile } from './tools/auth0/handlers/userAttributeProfiles';
|
|
19
19
|
import { AttackProtection } from './tools/auth0/handlers/attackProtection';
|
|
20
20
|
import { TokenExchangeProfile } from './tools/auth0/handlers/tokenExchangeProfiles';
|
|
21
|
+
import { RiskAssessment } from './tools/auth0/handlers/riskAssessment';
|
|
21
22
|
type SharedPaginationParams = {
|
|
22
23
|
checkpoint?: boolean;
|
|
23
24
|
paginate?: boolean;
|
|
@@ -90,6 +91,7 @@ export type Asset = {
|
|
|
90
91
|
export type Assets = Partial<{
|
|
91
92
|
actions: Action[] | null;
|
|
92
93
|
attackProtection: AttackProtection | null;
|
|
94
|
+
riskAssessment: RiskAssessment | null;
|
|
93
95
|
branding: (Asset & {
|
|
94
96
|
templates?: {
|
|
95
97
|
template: string;
|
|
@@ -147,7 +149,7 @@ export type CalculatedChanges = {
|
|
|
147
149
|
conflicts: Asset[];
|
|
148
150
|
create: Asset[];
|
|
149
151
|
};
|
|
150
|
-
export type AssetTypes = 'rules' | 'rulesConfigs' | 'hooks' | 'pages' | 'databases' | 'clientGrants' | 'resourceServers' | 'clients' | 'connections' | 'tenant' | 'emailProvider' | 'emailTemplates' | 'guardianFactors' | 'guardianFactorProviders' | 'guardianFactorTemplates' | 'guardianPhoneFactorMessageTypes' | 'guardianPhoneFactorSelectedProvider' | 'guardianPolicies' | 'roles' | 'actions' | 'organizations' | 'triggers' | 'attackProtection' | 'branding' | 'phoneProviders' | 'phoneTemplates' | 'logStreams' | 'prompts' | 'customDomains' | 'themes' | 'forms' | 'flows' | 'flowVaultConnections' | 'selfServiceProfiles' | 'networkACLs' | 'userAttributeProfiles' | 'connectionProfiles' | 'tokenExchangeProfiles';
|
|
152
|
+
export type AssetTypes = 'rules' | 'rulesConfigs' | 'hooks' | 'pages' | 'databases' | 'clientGrants' | 'resourceServers' | 'clients' | 'connections' | 'tenant' | 'emailProvider' | 'emailTemplates' | 'guardianFactors' | 'guardianFactorProviders' | 'guardianFactorTemplates' | 'guardianPhoneFactorMessageTypes' | 'guardianPhoneFactorSelectedProvider' | 'guardianPolicies' | 'roles' | 'actions' | 'organizations' | 'triggers' | 'attackProtection' | 'riskAssessment' | 'branding' | 'phoneProviders' | 'phoneTemplates' | 'logStreams' | 'prompts' | 'customDomains' | 'themes' | 'forms' | 'flows' | 'flowVaultConnections' | 'selfServiceProfiles' | 'networkACLs' | 'userAttributeProfiles' | 'connectionProfiles' | 'tokenExchangeProfiles';
|
|
151
153
|
export type KeywordMappings = {
|
|
152
154
|
[key: string]: (string | number)[] | string | number;
|
|
153
155
|
};
|