auth0-deploy-cli 8.23.2 → 8.25.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 +25 -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/directory/handlers/tenant.js +7 -2
- package/lib/context/directory/index.js +3 -0
- package/lib/context/index.js +10 -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/context/yaml/handlers/tenant.js +7 -2
- package/lib/context/yaml/index.js +5 -0
- package/lib/sessionDurationsToMinutes.d.ts +5 -1
- package/lib/sessionDurationsToMinutes.js +5 -1
- package/lib/tools/auth0/handlers/connections.d.ts +56 -1
- package/lib/tools/auth0/handlers/connections.js +200 -5
- package/lib/tools/auth0/handlers/index.d.ts +1 -0
- 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/auth0/handlers/tokenExchangeProfiles.d.ts +0 -14
- package/lib/tools/auth0/handlers/tokenExchangeProfiles.js +27 -34
- package/lib/tools/auth0/schema.d.ts +7 -0
- package/lib/tools/auth0/schema.js +11 -0
- package/lib/tools/constants.d.ts +1 -0
- package/lib/tools/constants.js +1 -0
- package/lib/tools/utils.d.ts +1 -0
- package/lib/tools/utils.js +14 -0
- package/lib/types.d.ts +7 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [8.25.0] - 2026-01-08
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `AUTH0_INCLUDED_CONNECTIONS` config property to include only selected `connection`. [#1242]
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Fix `tokenExchangeProfiles` profiles handling. [#1253]
|
|
19
|
+
- Fix `idle_ephemeral_session_lifetime` and `ephemeral_session_lifetime` handling while importing [#1261]
|
|
20
|
+
|
|
21
|
+
## [8.24.0] - 2025-12-22
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Add support for managing `riskAssessment` settings. [#1217]
|
|
26
|
+
- Add directory provisioning support for `google-apps` connections. [#1246]
|
|
27
|
+
|
|
10
28
|
## [8.23.2] - 2025-12-18
|
|
11
29
|
|
|
12
30
|
### Fixed
|
|
@@ -1575,6 +1593,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1575
1593
|
[#1211]: https://github.com/auth0/auth0-deploy-cli/issues/1211
|
|
1576
1594
|
[#1212]: https://github.com/auth0/auth0-deploy-cli/issues/1212
|
|
1577
1595
|
[#1214]: https://github.com/auth0/auth0-deploy-cli/issues/1214
|
|
1596
|
+
[#1217]: https://github.com/auth0/auth0-deploy-cli/issues/1217
|
|
1578
1597
|
[#1221]: https://github.com/auth0/auth0-deploy-cli/issues/1221
|
|
1579
1598
|
[#1223]: https://github.com/auth0/auth0-deploy-cli/issues/1223
|
|
1580
1599
|
[#1224]: https://github.com/auth0/auth0-deploy-cli/issues/1224
|
|
@@ -1583,8 +1602,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1583
1602
|
[#1232]: https://github.com/auth0/auth0-deploy-cli/issues/1232
|
|
1584
1603
|
[#1239]: https://github.com/auth0/auth0-deploy-cli/issues/1239
|
|
1585
1604
|
[#1240]: https://github.com/auth0/auth0-deploy-cli/issues/1240
|
|
1605
|
+
[#1242]: https://github.com/auth0/auth0-deploy-cli/issues/1242
|
|
1586
1606
|
[#1244]: https://github.com/auth0/auth0-deploy-cli/issues/1244
|
|
1587
|
-
[
|
|
1607
|
+
[#1246]: https://github.com/auth0/auth0-deploy-cli/issues/1246
|
|
1608
|
+
[#1253]: https://github.com/auth0/auth0-deploy-cli/issues/1253
|
|
1609
|
+
[Unreleased]: https://github.com/auth0/auth0-deploy-cli/compare/v8.25.0...HEAD
|
|
1610
|
+
[8.25.0]: https://github.com/auth0/auth0-deploy-cli/compare/v8.24.0...v8.25.0
|
|
1611
|
+
[8.24.0]: https://github.com/auth0/auth0-deploy-cli/compare/v8.23.2...v8.24.0
|
|
1588
1612
|
[8.23.2]: https://github.com/auth0/auth0-deploy-cli/compare/v8.23.1...v8.23.2
|
|
1589
1613
|
[8.23.1]: https://github.com/auth0/auth0-deploy-cli/compare/v8.23.0...v8.23.1
|
|
1590
1614
|
[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;
|
|
@@ -15,12 +15,17 @@ function parse(context) {
|
|
|
15
15
|
return { tenant: null };
|
|
16
16
|
}
|
|
17
17
|
/* eslint-disable camelcase */
|
|
18
|
-
const { session_lifetime, idle_session_lifetime, ...tenant } = (0, utils_1.loadJSON)(tenantFile, {
|
|
18
|
+
const { session_lifetime, idle_session_lifetime, idle_ephemeral_session_lifetime, ephemeral_session_lifetime, ...tenant } = (0, utils_1.loadJSON)(tenantFile, {
|
|
19
19
|
mappings: context.mappings,
|
|
20
20
|
disableKeywordReplacement: context.disableKeywordReplacement,
|
|
21
21
|
});
|
|
22
22
|
(0, utils_1.clearTenantFlags)(tenant);
|
|
23
|
-
const sessionDurations = (0, sessionDurationsToMinutes_1.sessionDurationsToMinutes)({
|
|
23
|
+
const sessionDurations = (0, sessionDurationsToMinutes_1.sessionDurationsToMinutes)({
|
|
24
|
+
session_lifetime,
|
|
25
|
+
idle_session_lifetime,
|
|
26
|
+
idle_ephemeral_session_lifetime,
|
|
27
|
+
ephemeral_session_lifetime,
|
|
28
|
+
});
|
|
24
29
|
return {
|
|
25
30
|
//@ts-ignore
|
|
26
31
|
tenant: {
|
|
@@ -63,6 +63,9 @@ class DirectoryContext {
|
|
|
63
63
|
resourceServers: config.AUTH0_EXCLUDED_RESOURCE_SERVERS || [],
|
|
64
64
|
defaults: config.AUTH0_EXCLUDED_DEFAULTS || [],
|
|
65
65
|
};
|
|
66
|
+
this.assets.include = {
|
|
67
|
+
connections: config.AUTH0_INCLUDED_CONNECTIONS || [],
|
|
68
|
+
};
|
|
66
69
|
}
|
|
67
70
|
loadFile(f, folder) {
|
|
68
71
|
const basePath = path.join(this.filePath, folder);
|
package/lib/context/index.js
CHANGED
|
@@ -26,6 +26,7 @@ const nonPrimitiveProps = [
|
|
|
26
26
|
'AUTH0_INCLUDED_ONLY',
|
|
27
27
|
'EXCLUDED_PROPS',
|
|
28
28
|
'INCLUDED_PROPS',
|
|
29
|
+
'AUTH0_INCLUDED_CONNECTIONS',
|
|
29
30
|
];
|
|
30
31
|
const EA_FEATURES = [];
|
|
31
32
|
const setupContext = async (config, command) => {
|
|
@@ -97,6 +98,15 @@ const setupContext = async (config, command) => {
|
|
|
97
98
|
logger_1.default.warn(`Usage of the ${usedDeprecatedParams.join(', ')} exclusion ${usedDeprecatedParams.length > 1 ? 'params are' : 'param is'} deprecated and may be removed from future major versions. See: https://github.com/auth0/auth0-deploy-cli/issues/451#user-content-deprecated-exclusion-props for details.`);
|
|
98
99
|
}
|
|
99
100
|
})(config);
|
|
101
|
+
((config) => {
|
|
102
|
+
const hasIncludedConnections = config.AUTH0_INCLUDED_CONNECTIONS !== undefined &&
|
|
103
|
+
config.AUTH0_INCLUDED_CONNECTIONS.length > 0;
|
|
104
|
+
const hasExcludedConnections = config.AUTH0_EXCLUDED_CONNECTIONS !== undefined &&
|
|
105
|
+
config.AUTH0_EXCLUDED_CONNECTIONS.length > 0;
|
|
106
|
+
if (hasIncludedConnections && hasExcludedConnections) {
|
|
107
|
+
throw new Error('Both AUTH0_INCLUDED_CONNECTIONS and AUTH0_EXCLUDED_CONNECTIONS configuration values are defined, only one can be configured at a time.');
|
|
108
|
+
}
|
|
109
|
+
})(config);
|
|
100
110
|
((config) => {
|
|
101
111
|
// Check if experimental early access features are enabled
|
|
102
112
|
if (config.AUTH0_EXPERIMENTAL_EA) {
|
|
@@ -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;
|
|
@@ -6,9 +6,14 @@ async function parse(context) {
|
|
|
6
6
|
if (!context.assets.tenant)
|
|
7
7
|
return { tenant: null };
|
|
8
8
|
/* eslint-disable camelcase */
|
|
9
|
-
const { session_lifetime, idle_session_lifetime, ...tenant } = context.assets.tenant;
|
|
9
|
+
const { session_lifetime, idle_session_lifetime, idle_ephemeral_session_lifetime, ephemeral_session_lifetime, ...tenant } = context.assets.tenant;
|
|
10
10
|
(0, utils_1.clearTenantFlags)(tenant);
|
|
11
|
-
const sessionDurations = (0, sessionDurationsToMinutes_1.sessionDurationsToMinutes)({
|
|
11
|
+
const sessionDurations = (0, sessionDurationsToMinutes_1.sessionDurationsToMinutes)({
|
|
12
|
+
session_lifetime,
|
|
13
|
+
idle_session_lifetime,
|
|
14
|
+
idle_ephemeral_session_lifetime,
|
|
15
|
+
ephemeral_session_lifetime,
|
|
16
|
+
});
|
|
12
17
|
return {
|
|
13
18
|
tenant: {
|
|
14
19
|
...tenant,
|
|
@@ -32,6 +32,9 @@ class YAMLContext {
|
|
|
32
32
|
resourceServers: config.AUTH0_EXCLUDED_RESOURCE_SERVERS || [],
|
|
33
33
|
defaults: config.AUTH0_EXCLUDED_DEFAULTS || [],
|
|
34
34
|
};
|
|
35
|
+
this.assets.include = {
|
|
36
|
+
connections: config.AUTH0_INCLUDED_CONNECTIONS || [],
|
|
37
|
+
};
|
|
35
38
|
this.basePath = (() => {
|
|
36
39
|
if (!!config.AUTH0_BASE_PATH)
|
|
37
40
|
return config.AUTH0_BASE_PATH;
|
|
@@ -80,6 +83,7 @@ class YAMLContext {
|
|
|
80
83
|
}, {});
|
|
81
84
|
const initialAssets = {
|
|
82
85
|
exclude: this.assets.exclude, // Keep the exclude rules in result assets
|
|
86
|
+
include: this.assets.include, // Keep the include rules in result assets
|
|
83
87
|
};
|
|
84
88
|
this.assets = Object.keys(this.assets).reduce((acc, key) => {
|
|
85
89
|
// Get the list of asset types to include
|
|
@@ -173,6 +177,7 @@ class YAMLContext {
|
|
|
173
177
|
let cleaned = (0, readonly_1.default)(this.assets, this.config);
|
|
174
178
|
// Delete exclude as it's not part of the auth0 tenant config
|
|
175
179
|
delete cleaned.exclude;
|
|
180
|
+
delete cleaned.include;
|
|
176
181
|
// Optionally Strip identifiers
|
|
177
182
|
if (!this.config.AUTH0_EXPORT_IDENTIFIERS) {
|
|
178
183
|
cleaned = (0, utils_1.stripIdentifiers)(auth0, cleaned);
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
export declare const sessionDurationsToMinutes: ({ session_lifetime, idle_session_lifetime, }: {
|
|
1
|
+
export declare const sessionDurationsToMinutes: ({ session_lifetime, idle_session_lifetime, idle_ephemeral_session_lifetime, ephemeral_session_lifetime, }: {
|
|
2
2
|
session_lifetime?: number;
|
|
3
3
|
idle_session_lifetime?: number;
|
|
4
|
+
idle_ephemeral_session_lifetime?: number;
|
|
5
|
+
ephemeral_session_lifetime?: number;
|
|
4
6
|
}) => {
|
|
5
7
|
session_lifetime_in_minutes?: number;
|
|
6
8
|
idle_session_lifetime_in_minutes?: number;
|
|
9
|
+
idle_ephemeral_session_lifetime_in_minutes?: number;
|
|
10
|
+
ephemeral_session_lifetime_in_minutes?: number;
|
|
7
11
|
};
|
|
@@ -4,12 +4,16 @@ exports.sessionDurationsToMinutes = void 0;
|
|
|
4
4
|
function hoursToMinutes(hours) {
|
|
5
5
|
return Math.round(hours * 60);
|
|
6
6
|
}
|
|
7
|
-
const sessionDurationsToMinutes = ({ session_lifetime, idle_session_lifetime, }) => {
|
|
7
|
+
const sessionDurationsToMinutes = ({ session_lifetime, idle_session_lifetime, idle_ephemeral_session_lifetime, ephemeral_session_lifetime, }) => {
|
|
8
8
|
const sessionDurations = {};
|
|
9
9
|
if (!!session_lifetime)
|
|
10
10
|
sessionDurations.session_lifetime_in_minutes = hoursToMinutes(session_lifetime);
|
|
11
11
|
if (!!idle_session_lifetime)
|
|
12
12
|
sessionDurations.idle_session_lifetime_in_minutes = hoursToMinutes(idle_session_lifetime);
|
|
13
|
+
if (!!idle_ephemeral_session_lifetime)
|
|
14
|
+
sessionDurations.idle_ephemeral_session_lifetime_in_minutes = hoursToMinutes(idle_ephemeral_session_lifetime);
|
|
15
|
+
if (!!ephemeral_session_lifetime)
|
|
16
|
+
sessionDurations.ephemeral_session_lifetime_in_minutes = hoursToMinutes(ephemeral_session_lifetime);
|
|
13
17
|
return sessionDurations;
|
|
14
18
|
};
|
|
15
19
|
exports.sessionDurationsToMinutes = sessionDurationsToMinutes;
|
|
@@ -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`.
|
|
@@ -361,11 +551,16 @@ class ConnectionsHandler extends default_1.default {
|
|
|
361
551
|
if (!isOptionExists) {
|
|
362
552
|
logger_1.default.warn(`Insufficient scope the update:connections_options scope is required to update ${this.type} options.`);
|
|
363
553
|
}
|
|
554
|
+
const includedConnections = (assets.include && assets.include.connections) || [];
|
|
364
555
|
const excludedConnections = (assets.exclude && assets.exclude.connections) || [];
|
|
365
|
-
|
|
366
|
-
|
|
556
|
+
let changes = await this.calcChanges(assets);
|
|
557
|
+
changes = (0, utils_1.filterExcluded)(changes, excludedConnections);
|
|
558
|
+
changes = (0, utils_1.filterIncluded)(changes, includedConnections);
|
|
559
|
+
await super.processChanges(assets, changes);
|
|
367
560
|
// process enabled clients
|
|
368
|
-
await (0, exports.processConnectionEnabledClients)(this.client, this.type,
|
|
561
|
+
await (0, exports.processConnectionEnabledClients)(this.client, this.type, changes);
|
|
562
|
+
// process directory provisioning
|
|
563
|
+
await this.processConnectionDirectoryProvisioning(changes);
|
|
369
564
|
}
|
|
370
565
|
}
|
|
371
566
|
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) {
|
|
@@ -11,10 +11,6 @@ export declare const schema: {
|
|
|
11
11
|
type: string;
|
|
12
12
|
description: string;
|
|
13
13
|
};
|
|
14
|
-
id: {
|
|
15
|
-
type: string;
|
|
16
|
-
description: string;
|
|
17
|
-
};
|
|
18
14
|
subject_token_type: {
|
|
19
15
|
type: string;
|
|
20
16
|
description: string;
|
|
@@ -28,16 +24,6 @@ export declare const schema: {
|
|
|
28
24
|
enum: string[];
|
|
29
25
|
description: string;
|
|
30
26
|
};
|
|
31
|
-
created_at: {
|
|
32
|
-
type: string;
|
|
33
|
-
format: string;
|
|
34
|
-
description: string;
|
|
35
|
-
};
|
|
36
|
-
updated_at: {
|
|
37
|
-
type: string;
|
|
38
|
-
format: string;
|
|
39
|
-
description: string;
|
|
40
|
-
};
|
|
41
27
|
};
|
|
42
28
|
required: string[];
|
|
43
29
|
};
|
|
@@ -55,10 +55,6 @@ exports.schema = {
|
|
|
55
55
|
type: 'string',
|
|
56
56
|
description: 'The name of the token exchange profile',
|
|
57
57
|
},
|
|
58
|
-
id: {
|
|
59
|
-
type: 'string',
|
|
60
|
-
description: 'The unique identifier of the token exchange profile',
|
|
61
|
-
},
|
|
62
58
|
subject_token_type: {
|
|
63
59
|
type: 'string',
|
|
64
60
|
description: 'The URI representing the subject token type',
|
|
@@ -72,16 +68,6 @@ exports.schema = {
|
|
|
72
68
|
enum: ['custom_authentication'],
|
|
73
69
|
description: 'The type of token exchange profile',
|
|
74
70
|
},
|
|
75
|
-
created_at: {
|
|
76
|
-
type: 'string',
|
|
77
|
-
format: 'date-time',
|
|
78
|
-
description: 'The timestamp when the profile was created',
|
|
79
|
-
},
|
|
80
|
-
updated_at: {
|
|
81
|
-
type: 'string',
|
|
82
|
-
format: 'date-time',
|
|
83
|
-
description: 'The timestamp when the profile was last updated',
|
|
84
|
-
},
|
|
85
71
|
},
|
|
86
72
|
required: ['name', 'subject_token_type', 'action', 'type'],
|
|
87
73
|
},
|
|
@@ -92,10 +78,10 @@ class TokenExchangeProfilesHandler extends default_1.default {
|
|
|
92
78
|
...config,
|
|
93
79
|
type: 'tokenExchangeProfiles',
|
|
94
80
|
id: 'id',
|
|
95
|
-
identifiers: ['id', '
|
|
81
|
+
identifiers: ['id', 'subject_token_type'],
|
|
96
82
|
// Only name and subject_token_type can be updated
|
|
97
|
-
stripUpdateFields: ['
|
|
98
|
-
stripCreateFields: ['
|
|
83
|
+
stripUpdateFields: ['created_at', 'updated_at', 'action_id', 'type'],
|
|
84
|
+
stripCreateFields: ['created_at', 'updated_at'],
|
|
99
85
|
});
|
|
100
86
|
}
|
|
101
87
|
sanitizeForExport(profile, actions) {
|
|
@@ -145,9 +131,9 @@ class TokenExchangeProfilesHandler extends default_1.default {
|
|
|
145
131
|
paginate: true,
|
|
146
132
|
});
|
|
147
133
|
// Fetch all actions to map action_id to action name
|
|
148
|
-
|
|
134
|
+
this.actions = await this.getActions();
|
|
149
135
|
// Map action_id to action name for each profile
|
|
150
|
-
this.existing = profiles.map((profile) => this.sanitizeForExport(profile, actions));
|
|
136
|
+
this.existing = profiles.map((profile) => this.sanitizeForExport(profile, this.actions ?? []));
|
|
151
137
|
return this.existing;
|
|
152
138
|
}
|
|
153
139
|
catch (err) {
|
|
@@ -163,31 +149,34 @@ class TokenExchangeProfilesHandler extends default_1.default {
|
|
|
163
149
|
// Do nothing if not set
|
|
164
150
|
if (!tokenExchangeProfiles)
|
|
165
151
|
return;
|
|
166
|
-
// Fetch actions to resolve action names to IDs
|
|
167
|
-
const actions = await this.getActions();
|
|
168
|
-
// Map action names to action_ids before processing
|
|
169
|
-
const sanitizedProfiles = tokenExchangeProfiles.map((profile) => this.sanitizeForAPI(profile, actions));
|
|
170
|
-
// Create modified assets with sanitized profiles
|
|
171
|
-
const modifiedAssets = {
|
|
172
|
-
...assets,
|
|
173
|
-
tokenExchangeProfiles: sanitizedProfiles,
|
|
174
|
-
};
|
|
175
152
|
// Calculate changes
|
|
176
|
-
const { del, update, create, conflicts } = await this.calcChanges(
|
|
153
|
+
const { del, update, create, conflicts } = await this.calcChanges(assets);
|
|
177
154
|
logger_1.default.debug(`Start processChanges for tokenExchangeProfiles [delete:${del.length}] [update:${update.length}], [create:${create.length}], [conflicts:${conflicts.length}]`);
|
|
155
|
+
// Fetch actions to resolve action names to IDs
|
|
156
|
+
if (!this.actions || this.actions.length === 0) {
|
|
157
|
+
this.actions = await this.getActions();
|
|
158
|
+
}
|
|
178
159
|
// Process changes in order: delete, create, update
|
|
179
160
|
if (del.length > 0) {
|
|
180
|
-
await this.deleteTokenExchangeProfiles(del);
|
|
161
|
+
await this.deleteTokenExchangeProfiles(del.map((profile) => this.sanitizeForAPI(profile, this.actions ?? [])));
|
|
181
162
|
}
|
|
182
163
|
if (create.length > 0) {
|
|
183
|
-
await this.createTokenExchangeProfiles(create);
|
|
164
|
+
await this.createTokenExchangeProfiles(create.map((profile) => this.sanitizeForAPI(profile, this.actions ?? [])));
|
|
184
165
|
}
|
|
185
166
|
if (update.length > 0) {
|
|
186
|
-
await this.updateTokenExchangeProfiles(update);
|
|
167
|
+
await this.updateTokenExchangeProfiles(update.map((profile) => this.sanitizeForAPI(profile, this.actions ?? [])));
|
|
187
168
|
}
|
|
188
169
|
}
|
|
189
170
|
async createTokenExchangeProfile(profile) {
|
|
190
|
-
|
|
171
|
+
if (!profile.name || !profile.subject_token_type || !profile.action_id || !profile.type) {
|
|
172
|
+
throw new Error(`Cannot create token exchange profile missing required fields`);
|
|
173
|
+
}
|
|
174
|
+
const createParams = {
|
|
175
|
+
name: profile.name,
|
|
176
|
+
subject_token_type: profile.subject_token_type,
|
|
177
|
+
action_id: profile.action_id,
|
|
178
|
+
type: profile.type,
|
|
179
|
+
};
|
|
191
180
|
const created = await this.client.tokenExchangeProfiles.create(createParams);
|
|
192
181
|
return created;
|
|
193
182
|
}
|
|
@@ -207,10 +196,14 @@ class TokenExchangeProfilesHandler extends default_1.default {
|
|
|
207
196
|
.promise();
|
|
208
197
|
}
|
|
209
198
|
async updateTokenExchangeProfile(profile) {
|
|
210
|
-
const { id,
|
|
199
|
+
const { id, name, subject_token_type } = profile;
|
|
211
200
|
if (!id) {
|
|
212
201
|
throw new Error(`Cannot update token exchange profile "${profile.name}" - missing id`);
|
|
213
202
|
}
|
|
203
|
+
const updateParams = {
|
|
204
|
+
name,
|
|
205
|
+
subject_token_type,
|
|
206
|
+
};
|
|
214
207
|
await this.client.tokenExchangeProfiles.update(id, updateParams);
|
|
215
208
|
}
|
|
216
209
|
async updateTokenExchangeProfiles(updates) {
|
|
@@ -14,6 +14,12 @@ const excludeSchema = Object.entries(handlers_1.default).reduce((map, [name, obj
|
|
|
14
14
|
}
|
|
15
15
|
return map;
|
|
16
16
|
}, {});
|
|
17
|
+
const includeSchema = Object.entries(handlers_1.default).reduce((map, [name, obj]) => {
|
|
18
|
+
if (obj.includeSchema) {
|
|
19
|
+
map[name] = obj.includeSchema;
|
|
20
|
+
}
|
|
21
|
+
return map;
|
|
22
|
+
}, {});
|
|
17
23
|
exports.default = {
|
|
18
24
|
type: 'object',
|
|
19
25
|
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
@@ -24,6 +30,11 @@ exports.default = {
|
|
|
24
30
|
properties: { ...excludeSchema },
|
|
25
31
|
default: {},
|
|
26
32
|
},
|
|
33
|
+
include: {
|
|
34
|
+
type: 'object',
|
|
35
|
+
properties: { ...includeSchema },
|
|
36
|
+
default: {},
|
|
37
|
+
},
|
|
27
38
|
},
|
|
28
39
|
additionalProperties: false,
|
|
29
40
|
};
|
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/tools/utils.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare function stripFields(obj: Asset, fields: string[]): Asset;
|
|
|
19
19
|
export declare function getEnabledClients(assets: Assets, connection: Asset, existing: Asset[], clients: Asset[]): string[] | undefined;
|
|
20
20
|
export declare function duplicateItems(arr: Asset[], key: string): Asset[];
|
|
21
21
|
export declare function filterExcluded(changes: CalculatedChanges, exclude: string[]): CalculatedChanges;
|
|
22
|
+
export declare function filterIncluded(changes: CalculatedChanges, include: string[]): CalculatedChanges;
|
|
22
23
|
export declare function areArraysEquals(x: any[], y: any[]): boolean;
|
|
23
24
|
export declare const obfuscateSensitiveValues: (data: Asset | Asset[] | null, sensitiveFieldsToObfuscate: string[]) => Asset | Asset[] | null;
|
|
24
25
|
export declare const stripObfuscatedFieldsFromPayload: (data: Asset | Asset[] | null, obfuscatedFields: string[]) => Asset | Asset[] | null;
|
package/lib/tools/utils.js
CHANGED
|
@@ -50,6 +50,7 @@ exports.stripFields = stripFields;
|
|
|
50
50
|
exports.getEnabledClients = getEnabledClients;
|
|
51
51
|
exports.duplicateItems = duplicateItems;
|
|
52
52
|
exports.filterExcluded = filterExcluded;
|
|
53
|
+
exports.filterIncluded = filterIncluded;
|
|
53
54
|
exports.areArraysEquals = areArraysEquals;
|
|
54
55
|
exports.sleep = sleep;
|
|
55
56
|
exports.maskSecretAtPath = maskSecretAtPath;
|
|
@@ -213,6 +214,19 @@ function filterExcluded(changes, exclude) {
|
|
|
213
214
|
conflicts: filter(conflicts),
|
|
214
215
|
};
|
|
215
216
|
}
|
|
217
|
+
function filterIncluded(changes, include) {
|
|
218
|
+
const { del, update, create, conflicts } = changes;
|
|
219
|
+
if (!include || !include.length) {
|
|
220
|
+
return changes;
|
|
221
|
+
}
|
|
222
|
+
const filter = (list) => list.filter((item) => include.includes(item.name));
|
|
223
|
+
return {
|
|
224
|
+
del: filter(del),
|
|
225
|
+
update: filter(update),
|
|
226
|
+
create: filter(create),
|
|
227
|
+
conflicts: filter(conflicts),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
216
230
|
function areArraysEquals(x, y) {
|
|
217
231
|
return lodash_1.default.isEqual(x && x.sort(), y && y.sort());
|
|
218
232
|
}
|
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;
|
|
@@ -75,6 +76,7 @@ export type Config = {
|
|
|
75
76
|
INCLUDED_PROPS?: {
|
|
76
77
|
[key: string]: string[];
|
|
77
78
|
};
|
|
79
|
+
AUTH0_INCLUDED_CONNECTIONS?: string[];
|
|
78
80
|
AUTH0_IGNORE_UNAVAILABLE_MIGRATIONS?: boolean;
|
|
79
81
|
AUTH0_EXCLUDED_RULES?: string[];
|
|
80
82
|
AUTH0_EXCLUDED_CLIENTS?: string[];
|
|
@@ -90,6 +92,7 @@ export type Asset = {
|
|
|
90
92
|
export type Assets = Partial<{
|
|
91
93
|
actions: Action[] | null;
|
|
92
94
|
attackProtection: AttackProtection | null;
|
|
95
|
+
riskAssessment: RiskAssessment | null;
|
|
93
96
|
branding: (Asset & {
|
|
94
97
|
templates?: {
|
|
95
98
|
template: string;
|
|
@@ -129,6 +132,9 @@ export type Assets = Partial<{
|
|
|
129
132
|
exclude?: {
|
|
130
133
|
[key: string]: string[];
|
|
131
134
|
};
|
|
135
|
+
include?: {
|
|
136
|
+
[key: string]: string[];
|
|
137
|
+
};
|
|
132
138
|
clientsOrig: Asset[] | null;
|
|
133
139
|
themes: Theme[] | null;
|
|
134
140
|
forms: Form[] | null;
|
|
@@ -147,7 +153,7 @@ export type CalculatedChanges = {
|
|
|
147
153
|
conflicts: Asset[];
|
|
148
154
|
create: Asset[];
|
|
149
155
|
};
|
|
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';
|
|
156
|
+
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
157
|
export type KeywordMappings = {
|
|
152
158
|
[key: string]: (string | number)[] | string | number;
|
|
153
159
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auth0-deploy-cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.25.0",
|
|
4
4
|
"description": "A command line tool for deploying updates to your Auth0 tenant",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"nconf": "^0.13.0",
|
|
43
43
|
"promise-pool-executor": "^1.1.1",
|
|
44
44
|
"sanitize-filename": "^1.6.3",
|
|
45
|
-
"undici": "^7.
|
|
45
|
+
"undici": "^7.18.0",
|
|
46
46
|
"winston": "^3.19.0",
|
|
47
47
|
"yargs": "^15.4.1"
|
|
48
48
|
},
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"@types/mocha": "^10.0.10",
|
|
53
53
|
"@types/nconf": "^0.10.7",
|
|
54
54
|
"@eslint/js": "^9.39.2",
|
|
55
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
56
|
-
"@typescript-eslint/parser": "^8.
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^8.52.0",
|
|
56
|
+
"@typescript-eslint/parser": "^8.52.0",
|
|
57
57
|
"chai": "^4.5.0",
|
|
58
58
|
"chai-as-promised": "^7.1.2",
|
|
59
59
|
"eslint": "^9.39.2",
|