auth0-deploy-cli 8.44.0 → 8.45.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 +24 -1
- package/README.md +1 -1
- package/lib/context/directory/handlers/index.js +2 -0
- package/lib/context/directory/handlers/networkACLKeys.d.ts +6 -0
- package/lib/context/directory/handlers/networkACLKeys.js +54 -0
- package/lib/context/yaml/handlers/index.js +2 -0
- package/lib/context/yaml/handlers/networkACLKeys.d.ts +6 -0
- package/lib/context/yaml/handlers/networkACLKeys.js +42 -0
- package/lib/keywordPreservation.d.ts +1 -1
- package/lib/keywordPreservation.js +2 -1
- package/lib/tools/auth0/handlers/clients.d.ts +19 -0
- package/lib/tools/auth0/handlers/clients.js +37 -1
- package/lib/tools/auth0/handlers/databases.d.ts +28 -0
- package/lib/tools/auth0/handlers/databases.js +46 -21
- package/lib/tools/auth0/handlers/index.js +2 -0
- package/lib/tools/auth0/handlers/networkACLKeys.d.ts +45 -0
- package/lib/tools/auth0/handlers/networkACLKeys.js +177 -0
- package/lib/tools/auth0/handlers/networkACLs.d.ts +114 -2
- package/lib/tools/auth0/handlers/networkACLs.js +91 -16
- package/lib/tools/auth0/handlers/organizations.js +10 -4
- 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 +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [8.45.0] - 2026-09-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Support `b2b_integration_configuration` for Enterprise Connect (EA). [#1486]
|
|
15
|
+
- Add `networkACLKeys` handler for HMAC signature key management. [#1480]
|
|
16
|
+
- Support `match_all` in network ACL rules for unconditional block/allow. [#1483]
|
|
17
|
+
- Add `otp_settings` support for database connections. [#1481]
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Prevent export crash when a handler has no identifiers during keyword preservation. [#1487]
|
|
22
|
+
- Catch `feature_not_enabled` via `err.body.errorCode` and 400 status in organizations handler. [#1482]
|
|
23
|
+
- Prevent false `enabled_clients` diff in database dry-run. [#1479]
|
|
24
|
+
|
|
10
25
|
## [8.44.0] - 2026-08-26
|
|
11
26
|
|
|
12
27
|
### Added
|
|
@@ -1955,7 +1970,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1955
1970
|
[#1474]: https://github.com/auth0/auth0-deploy-cli/issues/1474
|
|
1956
1971
|
[#1476]: https://github.com/auth0/auth0-deploy-cli/issues/1476
|
|
1957
1972
|
[#1477]: https://github.com/auth0/auth0-deploy-cli/issues/1477
|
|
1958
|
-
[
|
|
1973
|
+
[#1479]: https://github.com/auth0/auth0-deploy-cli/issues/1479
|
|
1974
|
+
[#1480]: https://github.com/auth0/auth0-deploy-cli/issues/1480
|
|
1975
|
+
[#1481]: https://github.com/auth0/auth0-deploy-cli/issues/1481
|
|
1976
|
+
[#1482]: https://github.com/auth0/auth0-deploy-cli/issues/1482
|
|
1977
|
+
[#1483]: https://github.com/auth0/auth0-deploy-cli/issues/1483
|
|
1978
|
+
[#1486]: https://github.com/auth0/auth0-deploy-cli/issues/1486
|
|
1979
|
+
[#1487]: https://github.com/auth0/auth0-deploy-cli/issues/1487
|
|
1980
|
+
[Unreleased]: https://github.com/auth0/auth0-deploy-cli/compare/v8.45.0...HEAD
|
|
1981
|
+
[8.45.0]: https://github.com/auth0/auth0-deploy-cli/compare/v8.44.0...v8.45.0
|
|
1959
1982
|
[8.44.0]: https://github.com/auth0/auth0-deploy-cli/compare/v8.43.0...v8.44.0
|
|
1960
1983
|
[8.43.0]: https://github.com/auth0/auth0-deploy-cli/compare/v8.42.0...v8.43.0
|
|
1961
1984
|
[8.42.0]: https://github.com/auth0/auth0-deploy-cli/compare/v8.41.0...v8.42.0
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
The Auth0 Deploy CLI is a tool that helps you manage your Auth0 tenant configuration. It integrates into your development workflows as a standalone CLI or as a node module.
|
|
10
10
|
|
|
11
|
-
**Supported resource types:** actions, branding, client grants, clients (applications), connections, databases, custom domains, email templates, emails, grants, guardian, hook secrets, log streams, organizations, pages, prompts, resource servers (APIs), roles, tenant settings, themes, forms, flows, self-service profiles, network ACLs.
|
|
11
|
+
**Supported resource types:** actions, branding, client grants, clients (applications), connections, databases, custom domains, email templates, emails, grants, guardian, hook secrets, log streams, organizations, pages, prompts, resource servers (APIs), roles, tenant settings, themes, forms, flows, self-service profiles, network ACLs, network ACL keys.
|
|
12
12
|
|
|
13
13
|
🎢 [Highlights](#highlights) • 📚 [Documentation](#documentation) • 🚀 [Getting Started](#getting-started) • 📝 [Feedback](#feedback) • 💬 [Discussions](https://github.com/auth0/auth0-deploy-cli/discussions)
|
|
14
14
|
|
|
@@ -38,6 +38,7 @@ const rulesConfigs_1 = __importDefault(require("./rulesConfigs"));
|
|
|
38
38
|
const forms_1 = __importDefault(require("./forms"));
|
|
39
39
|
const flows_1 = __importDefault(require("./flows"));
|
|
40
40
|
const flowVaultConnections_1 = __importDefault(require("./flowVaultConnections"));
|
|
41
|
+
const networkACLKeys_1 = __importDefault(require("./networkACLKeys"));
|
|
41
42
|
const networkACLs_1 = __importDefault(require("./networkACLs"));
|
|
42
43
|
const userAttributeProfiles_1 = __importDefault(require("./userAttributeProfiles"));
|
|
43
44
|
const connectionProfiles_1 = __importDefault(require("./connectionProfiles"));
|
|
@@ -84,6 +85,7 @@ const directoryHandlers = {
|
|
|
84
85
|
flows: flows_1.default,
|
|
85
86
|
flowVaultConnections: flowVaultConnections_1.default,
|
|
86
87
|
selfServiceProfiles: selfServiceProfiles_1.default,
|
|
88
|
+
networkACLKeys: networkACLKeys_1.default,
|
|
87
89
|
networkACLs: networkACLs_1.default,
|
|
88
90
|
userAttributeProfiles: userAttributeProfiles_1.default,
|
|
89
91
|
connectionProfiles: connectionProfiles_1.default,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DirectoryHandler } from '.';
|
|
2
|
+
import { ParsedAsset } from '../../../types';
|
|
3
|
+
import { NetworkAclKey } from '../../../tools/auth0/handlers/networkACLKeys';
|
|
4
|
+
type ParsedNetworkACLKeys = ParsedAsset<'networkACLKeys', NetworkAclKey[]>;
|
|
5
|
+
declare const networkACLKeysHandler: DirectoryHandler<ParsedNetworkACLKeys>;
|
|
6
|
+
export default networkACLKeysHandler;
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
const logger_1 = __importDefault(require("../../../logger"));
|
|
11
|
+
function parse(context) {
|
|
12
|
+
const networkACLKeysDirectory = path_1.default.join(context.filePath, tools_1.constants.NETWORK_ACL_KEYS_DIRECTORY);
|
|
13
|
+
if (!(0, utils_1.existsMustBeDir)(networkACLKeysDirectory))
|
|
14
|
+
return { networkACLKeys: null }; // Skip
|
|
15
|
+
const foundFiles = (0, utils_1.getFiles)(networkACLKeysDirectory, ['.json']);
|
|
16
|
+
const networkACLKeys = foundFiles
|
|
17
|
+
.map((f) => (0, utils_1.loadJSON)(f, {
|
|
18
|
+
mappings: context.mappings,
|
|
19
|
+
disableKeywordReplacement: context.disableKeywordReplacement,
|
|
20
|
+
}))
|
|
21
|
+
.filter((p) => Object.keys(p).length > 0); // Filter out empty configs
|
|
22
|
+
return {
|
|
23
|
+
networkACLKeys,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async function dump(context) {
|
|
27
|
+
const { networkACLKeys } = context.assets;
|
|
28
|
+
if (!networkACLKeys)
|
|
29
|
+
return; // Skip, nothing to dump
|
|
30
|
+
if (Array.isArray(networkACLKeys) && networkACLKeys.length === 0) {
|
|
31
|
+
logger_1.default.info('No network ACL keys available, skipping dump');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const networkACLKeysDirectory = path_1.default.join(context.filePath, tools_1.constants.NETWORK_ACL_KEYS_DIRECTORY);
|
|
35
|
+
fs_extra_1.default.ensureDirSync(networkACLKeysDirectory);
|
|
36
|
+
// value is write-only — never returned by the API and must not be exported.
|
|
37
|
+
// created_at and updated_at are API-generated metadata; not needed in config.
|
|
38
|
+
const removeKeysFromOutput = ['value', 'created_at', 'updated_at'];
|
|
39
|
+
networkACLKeys.forEach((networkACLKey) => {
|
|
40
|
+
const out = { ...networkACLKey };
|
|
41
|
+
removeKeysFromOutput.forEach((key) => {
|
|
42
|
+
if (key in out)
|
|
43
|
+
delete out[key];
|
|
44
|
+
});
|
|
45
|
+
const fileName = (0, utils_1.sanitize)(networkACLKey.name);
|
|
46
|
+
const filePath = path_1.default.join(networkACLKeysDirectory, `${fileName}.json`);
|
|
47
|
+
(0, utils_1.dumpJSON)(filePath, out);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const networkACLKeysHandler = {
|
|
51
|
+
parse,
|
|
52
|
+
dump,
|
|
53
|
+
};
|
|
54
|
+
exports.default = networkACLKeysHandler;
|
|
@@ -38,6 +38,7 @@ const hooks_1 = __importDefault(require("./hooks"));
|
|
|
38
38
|
const forms_1 = __importDefault(require("./forms"));
|
|
39
39
|
const flows_1 = __importDefault(require("./flows"));
|
|
40
40
|
const flowVaultConnections_1 = __importDefault(require("./flowVaultConnections"));
|
|
41
|
+
const networkACLKeys_1 = __importDefault(require("./networkACLKeys"));
|
|
41
42
|
const networkACLs_1 = __importDefault(require("./networkACLs"));
|
|
42
43
|
const userAttributeProfiles_1 = __importDefault(require("./userAttributeProfiles"));
|
|
43
44
|
const connectionProfiles_1 = __importDefault(require("./connectionProfiles"));
|
|
@@ -84,6 +85,7 @@ const yamlHandlers = {
|
|
|
84
85
|
flows: flows_1.default,
|
|
85
86
|
flowVaultConnections: flowVaultConnections_1.default,
|
|
86
87
|
selfServiceProfiles: selfServiceProfiles_1.default,
|
|
88
|
+
networkACLKeys: networkACLKeys_1.default,
|
|
87
89
|
networkACLs: networkACLs_1.default,
|
|
88
90
|
userAttributeProfiles: userAttributeProfiles_1.default,
|
|
89
91
|
connectionProfiles: connectionProfiles_1.default,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { YAMLHandler } from '.';
|
|
2
|
+
import { ParsedAsset } from '../../../types';
|
|
3
|
+
import { NetworkAclKey } from '../../../tools/auth0/handlers/networkACLKeys';
|
|
4
|
+
type ParsedNetworkACLKeys = ParsedAsset<'networkACLKeys', NetworkAclKey[]>;
|
|
5
|
+
declare const networkACLKeysHandler: YAMLHandler<ParsedNetworkACLKeys>;
|
|
6
|
+
export default networkACLKeysHandler;
|
|
@@ -0,0 +1,42 @@
|
|
|
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 logger_1 = __importDefault(require("../../../logger"));
|
|
7
|
+
async function parse(context) {
|
|
8
|
+
const { networkACLKeys } = context.assets;
|
|
9
|
+
if (!networkACLKeys)
|
|
10
|
+
return { networkACLKeys: null };
|
|
11
|
+
return {
|
|
12
|
+
networkACLKeys,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async function dump(context) {
|
|
16
|
+
let { networkACLKeys } = context.assets;
|
|
17
|
+
if (!networkACLKeys)
|
|
18
|
+
return { networkACLKeys: null };
|
|
19
|
+
if (Array.isArray(networkACLKeys) && networkACLKeys.length === 0) {
|
|
20
|
+
logger_1.default.info('No network ACL keys available, skipping dump');
|
|
21
|
+
return { networkACLKeys: null };
|
|
22
|
+
}
|
|
23
|
+
// value is write-only — never returned by the API and must not be exported.
|
|
24
|
+
// created_at and updated_at are API-generated metadata; not needed in config.
|
|
25
|
+
const removeKeysFromOutput = ['value', 'created_at', 'updated_at'];
|
|
26
|
+
networkACLKeys = networkACLKeys.map((key) => {
|
|
27
|
+
const out = { ...key };
|
|
28
|
+
removeKeysFromOutput.forEach((k) => {
|
|
29
|
+
if (k in out)
|
|
30
|
+
delete out[k];
|
|
31
|
+
});
|
|
32
|
+
return out;
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
networkACLKeys,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const networkACLKeysHandler = {
|
|
39
|
+
parse,
|
|
40
|
+
dump,
|
|
41
|
+
};
|
|
42
|
+
exports.default = networkACLKeysHandler;
|
|
@@ -10,6 +10,6 @@ export declare const preserveKeywords: ({ localAssets, remoteAssets, keywordMapp
|
|
|
10
10
|
remoteAssets: object;
|
|
11
11
|
keywordMappings: KeywordMappings;
|
|
12
12
|
auth0Handlers: (Pick<APIHandler, "id" | "type"> & {
|
|
13
|
-
identifiers
|
|
13
|
+
identifiers?: (string | string[])[];
|
|
14
14
|
})[];
|
|
15
15
|
}) => object;
|
|
@@ -164,7 +164,8 @@ const preserveKeywords = ({ localAssets, remoteAssets, keywordMappings, auth0Han
|
|
|
164
164
|
if (Object.keys(keywordMappings).length === 0)
|
|
165
165
|
return remoteAssets;
|
|
166
166
|
const resourceSpecificIdentifiers = auth0Handlers.reduce((acc, handler) => {
|
|
167
|
-
|
|
167
|
+
// Standalone handlers (e.g. clientAuthCredentials) don't extend APIHandler and have no identifiers.
|
|
168
|
+
acc[handler.type] = (handler.identifiers ?? []).flat();
|
|
168
169
|
return acc;
|
|
169
170
|
}, {});
|
|
170
171
|
const addresses = (0, exports.getPreservableFieldsFromAssets)(localAssets, keywordMappings, resourceSpecificIdentifiers, '');
|
|
@@ -209,6 +209,25 @@ export declare const schema: {
|
|
|
209
209
|
type: string;
|
|
210
210
|
description: string;
|
|
211
211
|
};
|
|
212
|
+
b2b_integration_configuration: {
|
|
213
|
+
type: string[];
|
|
214
|
+
description: string;
|
|
215
|
+
properties: {
|
|
216
|
+
integration_type: {
|
|
217
|
+
type: string;
|
|
218
|
+
enum: string[];
|
|
219
|
+
description: string;
|
|
220
|
+
};
|
|
221
|
+
sso_profiles: {
|
|
222
|
+
type: string;
|
|
223
|
+
description: string;
|
|
224
|
+
items: {
|
|
225
|
+
type: string;
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
additionalProperties: boolean;
|
|
230
|
+
};
|
|
212
231
|
resource_server_identifier: {
|
|
213
232
|
type: string;
|
|
214
233
|
description: string;
|
|
@@ -292,6 +292,23 @@ exports.schema = {
|
|
|
292
292
|
type: 'string',
|
|
293
293
|
description: 'The type of application this client represents',
|
|
294
294
|
},
|
|
295
|
+
b2b_integration_configuration: {
|
|
296
|
+
type: ['object', 'null'],
|
|
297
|
+
description: 'B2B integration configuration. Early Access. Required feature flag: enterprise_connect_entitled.',
|
|
298
|
+
properties: {
|
|
299
|
+
integration_type: {
|
|
300
|
+
type: 'string',
|
|
301
|
+
enum: ['custom_auth_server', 'third_party', 'application'],
|
|
302
|
+
description: 'The type of integration used to connect to this B2B integration client.',
|
|
303
|
+
},
|
|
304
|
+
sso_profiles: {
|
|
305
|
+
type: 'array',
|
|
306
|
+
description: 'List of SSO profile IDs linked to this B2B integration client. Maximum 1 entry.',
|
|
307
|
+
items: { type: 'string' },
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
additionalProperties: false,
|
|
311
|
+
},
|
|
295
312
|
resource_server_identifier: {
|
|
296
313
|
type: 'string',
|
|
297
314
|
description: 'The identifier of a resource server in your tenant. This property links a client to a resource server indicating that the client IS that resource server. Can only be set when app_type=resource_server.',
|
|
@@ -584,6 +601,9 @@ class ClientHandler extends default_1.default {
|
|
|
584
601
|
'jwks_uri',
|
|
585
602
|
// third_party_security_mode is immutable after creation; PATCH returns 400
|
|
586
603
|
'third_party_security_mode',
|
|
604
|
+
// API-generated timestamps; PATCH returns 400 if present
|
|
605
|
+
'created_at',
|
|
606
|
+
'updated_at',
|
|
587
607
|
],
|
|
588
608
|
functions: {
|
|
589
609
|
create: (client) => this.createClient(client),
|
|
@@ -773,7 +793,23 @@ class ClientHandler extends default_1.default {
|
|
|
773
793
|
async updateClient(clientId, client) {
|
|
774
794
|
// For non-CIMD clients
|
|
775
795
|
if (!this.isCimdClient(client)) {
|
|
776
|
-
|
|
796
|
+
const payload = { ...client };
|
|
797
|
+
// b2b_integration_configuration: PATCH only allowed if client already has the object.
|
|
798
|
+
// Sending it to a client that lacks it returns 400 invalid_body.
|
|
799
|
+
// null clears the object — but only for clients that already have it; stripping
|
|
800
|
+
// null for a client without the field is a safe no-op.
|
|
801
|
+
if ('b2b_integration_configuration' in payload) {
|
|
802
|
+
const existing = (this.existing || []).find((c) => c.client_id === (client.client_id || clientId));
|
|
803
|
+
if (!existing?.b2b_integration_configuration) {
|
|
804
|
+
if (payload.b2b_integration_configuration !== null) {
|
|
805
|
+
logger_1.default.warn(`b2b_integration_configuration cannot be added to an existing client via PATCH ` +
|
|
806
|
+
`(client: ${client.name || clientId}). Skipping field. ` +
|
|
807
|
+
`Re-create the client to set this field.`);
|
|
808
|
+
}
|
|
809
|
+
delete payload.b2b_integration_configuration;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
return this.client.clients.update(clientId, payload);
|
|
777
813
|
}
|
|
778
814
|
const updatePayload = this.getCIMDEditableFields(client);
|
|
779
815
|
const registrationClientId = client.client_id || clientId;
|
|
@@ -195,6 +195,33 @@ export declare const schema: {
|
|
|
195
195
|
};
|
|
196
196
|
};
|
|
197
197
|
};
|
|
198
|
+
otp_settings: {
|
|
199
|
+
type: string;
|
|
200
|
+
properties: {
|
|
201
|
+
email: {
|
|
202
|
+
type: string;
|
|
203
|
+
properties: {
|
|
204
|
+
otp_length: {
|
|
205
|
+
type: string;
|
|
206
|
+
};
|
|
207
|
+
otp_expiry: {
|
|
208
|
+
type: string;
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
phone: {
|
|
213
|
+
type: string;
|
|
214
|
+
properties: {
|
|
215
|
+
otp_length: {
|
|
216
|
+
type: string;
|
|
217
|
+
};
|
|
218
|
+
otp_expiry: {
|
|
219
|
+
type: string;
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
};
|
|
198
225
|
password_options: {
|
|
199
226
|
type: string;
|
|
200
227
|
properties: {
|
|
@@ -295,6 +322,7 @@ export default class DatabaseHandler extends DefaultAPIHandler {
|
|
|
295
322
|
private validatePasswordlessSettings;
|
|
296
323
|
private validateEmailUniqueConstraints;
|
|
297
324
|
getClientFN(fn: 'create' | 'delete' | 'getAll' | 'update'): Function;
|
|
325
|
+
private enrichConnectionsWithEnabledClients;
|
|
298
326
|
getType(): Promise<Connection[]>;
|
|
299
327
|
calcChanges(assets: Assets): Promise<CalculatedChanges>;
|
|
300
328
|
dryRunChanges(assets: Assets): Promise<CalculatedChanges>;
|
|
@@ -181,6 +181,25 @@ exports.schema = {
|
|
|
181
181
|
action_id: { type: 'string' },
|
|
182
182
|
},
|
|
183
183
|
},
|
|
184
|
+
otp_settings: {
|
|
185
|
+
type: 'object',
|
|
186
|
+
properties: {
|
|
187
|
+
email: {
|
|
188
|
+
type: 'object',
|
|
189
|
+
properties: {
|
|
190
|
+
otp_length: { type: 'integer' },
|
|
191
|
+
otp_expiry: { type: 'integer' },
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
phone: {
|
|
195
|
+
type: 'object',
|
|
196
|
+
properties: {
|
|
197
|
+
otp_length: { type: 'integer' },
|
|
198
|
+
otp_expiry: { type: 'integer' },
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
184
203
|
password_options: {
|
|
185
204
|
type: 'object',
|
|
186
205
|
properties: {
|
|
@@ -419,6 +438,22 @@ class DatabaseHandler extends default_1.default {
|
|
|
419
438
|
}
|
|
420
439
|
return this.client.connections[fn].bind(this.client.connections);
|
|
421
440
|
}
|
|
441
|
+
// `enabled_clients` is no longer returned by connections.list; it must be fetched from the
|
|
442
|
+
// dedicated enabled-clients endpoint. Enriching the remote connections keeps the diff and the
|
|
443
|
+
// excluded-client preservation in `getEnabledClients` correct. Without it the dry-run diff
|
|
444
|
+
// reports a false "found in localObj but not in remoteObj" and a real import can silently
|
|
445
|
+
// disable an excluded-but-enabled client.
|
|
446
|
+
async enrichConnectionsWithEnabledClients(connections) {
|
|
447
|
+
return Promise.all(connections.map(async (con) => {
|
|
448
|
+
if (!con?.id)
|
|
449
|
+
return con;
|
|
450
|
+
const enabledClients = await (0, connections_1.getConnectionEnabledClients)(this.client, con.id);
|
|
451
|
+
if (enabledClients?.length) {
|
|
452
|
+
return { ...con, enabled_clients: enabledClients };
|
|
453
|
+
}
|
|
454
|
+
return con;
|
|
455
|
+
}));
|
|
456
|
+
}
|
|
422
457
|
async getType() {
|
|
423
458
|
if (this.existing)
|
|
424
459
|
return this.existing;
|
|
@@ -433,16 +468,7 @@ class DatabaseHandler extends default_1.default {
|
|
|
433
468
|
include_totals: true,
|
|
434
469
|
}),
|
|
435
470
|
]);
|
|
436
|
-
const dbConnectionsWithEnabledClients = await
|
|
437
|
-
if (!con?.id)
|
|
438
|
-
return con;
|
|
439
|
-
const enabledClients = await (0, connections_1.getConnectionEnabledClients)(this.client, con.id);
|
|
440
|
-
const connection = { ...con };
|
|
441
|
-
if (enabledClients && enabledClients?.length) {
|
|
442
|
-
connection.enabled_clients = enabledClients;
|
|
443
|
-
}
|
|
444
|
-
return connection;
|
|
445
|
-
}));
|
|
471
|
+
const dbConnectionsWithEnabledClients = await this.enrichConnectionsWithEnabledClients(connections);
|
|
446
472
|
// Convert action ID back to action name for export
|
|
447
473
|
const dbConnectionsWithActionNames = dbConnectionsWithEnabledClients.map((connection) => {
|
|
448
474
|
if (connection.options && 'custom_password_hash' in connection.options) {
|
|
@@ -489,28 +515,26 @@ class DatabaseHandler extends default_1.default {
|
|
|
489
515
|
update: [],
|
|
490
516
|
conflicts: [],
|
|
491
517
|
};
|
|
492
|
-
// Convert enabled_clients by name to the id
|
|
493
|
-
//
|
|
494
|
-
|
|
518
|
+
// Convert enabled_clients by name to the id. `getType()` fetches and enriches the existing
|
|
519
|
+
// connections with `enabled_clients` and caches the result in `this.existing`, so the
|
|
520
|
+
// `super.calcChanges()` call below reuses it instead of fetching again.
|
|
521
|
+
const [clients, actions, existingWithEnabledClients] = await Promise.all([
|
|
495
522
|
(0, client_1.paginate)(this.client.clients.list, {
|
|
496
523
|
paginate: true,
|
|
497
524
|
}),
|
|
498
|
-
(0, client_1.paginate)(this.client.connections.list, {
|
|
499
|
-
strategy: [auth0_1.Management.ConnectionStrategyEnum.Auth0],
|
|
500
|
-
checkpoint: true,
|
|
501
|
-
include_totals: true,
|
|
502
|
-
}),
|
|
503
525
|
(0, client_1.paginate)(this.client.actions.list, {
|
|
504
526
|
paginate: true,
|
|
505
527
|
include_totals: true,
|
|
506
528
|
}),
|
|
529
|
+
this.getType(),
|
|
507
530
|
]);
|
|
531
|
+
const existingConnections = existingWithEnabledClients || [];
|
|
508
532
|
const formatted = databases.map((db) => {
|
|
509
533
|
const { options, ...rest } = db;
|
|
510
534
|
const formattedOptions = this.getFormattedOptions(options, actions);
|
|
511
535
|
const formattedDb = { ...rest, options: formattedOptions };
|
|
512
536
|
if (db.enabled_clients) {
|
|
513
|
-
formattedDb.enabled_clients = (0, utils_1.getEnabledClients)(assets, db,
|
|
537
|
+
formattedDb.enabled_clients = (0, utils_1.getEnabledClients)(assets, db, existingConnections, clients);
|
|
514
538
|
}
|
|
515
539
|
return formattedDb;
|
|
516
540
|
});
|
|
@@ -540,19 +564,20 @@ class DatabaseHandler extends default_1.default {
|
|
|
540
564
|
include_totals: true,
|
|
541
565
|
}),
|
|
542
566
|
]);
|
|
567
|
+
const existingWithEnabledClients = await this.enrichConnectionsWithEnabledClients(existingDatabasesConnections);
|
|
543
568
|
const formatted = databases.map((db) => {
|
|
544
569
|
const { options, ...rest } = db;
|
|
545
570
|
const formattedOptions = this.getFormattedOptions(options, actions);
|
|
546
571
|
const formattedDb = { ...rest, options: formattedOptions };
|
|
547
572
|
if (db.enabled_clients) {
|
|
548
|
-
formattedDb.enabled_clients = (0, utils_1.getEnabledClients)(assets, db,
|
|
573
|
+
formattedDb.enabled_clients = (0, utils_1.getEnabledClients)(assets, db, existingWithEnabledClients, clients);
|
|
549
574
|
}
|
|
550
575
|
return formattedDb;
|
|
551
576
|
});
|
|
552
577
|
return (0, calculateDryRunChanges_1.calculateDryRunChanges)({
|
|
553
578
|
type: this.type,
|
|
554
579
|
assets: formatted,
|
|
555
|
-
existing:
|
|
580
|
+
existing: existingWithEnabledClients,
|
|
556
581
|
identifiers: this.identifiers,
|
|
557
582
|
ignoreDryRunFields: this.getEffectiveIgnoreDryRunFields(),
|
|
558
583
|
});
|
|
@@ -69,6 +69,7 @@ const forms = __importStar(require("./forms"));
|
|
|
69
69
|
const flows = __importStar(require("./flows"));
|
|
70
70
|
const flowVaultConnections = __importStar(require("./flowVaultConnections"));
|
|
71
71
|
const selfServiceProfiles = __importStar(require("./selfServiceProfiles"));
|
|
72
|
+
const networkACLKeys = __importStar(require("./networkACLKeys"));
|
|
72
73
|
const networkACLs = __importStar(require("./networkACLs"));
|
|
73
74
|
const userAttributeProfiles = __importStar(require("./userAttributeProfiles"));
|
|
74
75
|
const connectionProfiles = __importStar(require("./connectionProfiles"));
|
|
@@ -116,6 +117,7 @@ const auth0ApiHandlers = {
|
|
|
116
117
|
flows,
|
|
117
118
|
flowVaultConnections,
|
|
118
119
|
selfServiceProfiles,
|
|
120
|
+
networkACLKeys,
|
|
119
121
|
networkACLs,
|
|
120
122
|
userAttributeProfiles,
|
|
121
123
|
connectionProfiles,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Management } from 'auth0';
|
|
2
|
+
import DefaultAPIHandler from './default';
|
|
3
|
+
import { Asset, Assets, CalculatedChanges } from '../../../types';
|
|
4
|
+
export type NetworkAclKey = Management.NetworkAclKey & {
|
|
5
|
+
value?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const schema: {
|
|
8
|
+
type: string;
|
|
9
|
+
description: string;
|
|
10
|
+
items: {
|
|
11
|
+
type: string;
|
|
12
|
+
required: string[];
|
|
13
|
+
properties: {
|
|
14
|
+
id: {
|
|
15
|
+
type: string;
|
|
16
|
+
};
|
|
17
|
+
name: {
|
|
18
|
+
type: string;
|
|
19
|
+
maxLength: number;
|
|
20
|
+
};
|
|
21
|
+
alg: {
|
|
22
|
+
type: string;
|
|
23
|
+
enum: string[];
|
|
24
|
+
};
|
|
25
|
+
value: {
|
|
26
|
+
type: string;
|
|
27
|
+
};
|
|
28
|
+
fingerprint: {
|
|
29
|
+
type: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
additionalProperties: boolean;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export default class NetworkACLKeysHandler extends DefaultAPIHandler {
|
|
36
|
+
existing: NetworkAclKey[] | null;
|
|
37
|
+
constructor(config: DefaultAPIHandler);
|
|
38
|
+
objString(key: NetworkAclKey): string;
|
|
39
|
+
getType(): Promise<Asset | null>;
|
|
40
|
+
processChanges(assets: Assets): Promise<void>;
|
|
41
|
+
createNetworkACLKey(key: NetworkAclKey): Promise<void>;
|
|
42
|
+
createNetworkACLKeys(creates: CalculatedChanges['create']): Promise<void>;
|
|
43
|
+
deleteNetworkACLKey(key: NetworkAclKey): Promise<void>;
|
|
44
|
+
deleteNetworkACLKeys(data: Asset[]): Promise<void>;
|
|
45
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
42
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.schema = void 0;
|
|
46
|
+
const default_1 = __importStar(require("./default"));
|
|
47
|
+
const logger_1 = __importDefault(require("../../../logger"));
|
|
48
|
+
exports.schema = {
|
|
49
|
+
type: 'array',
|
|
50
|
+
description: 'List of Network ACL keys for HMAC signature verification',
|
|
51
|
+
items: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
required: ['name', 'alg'],
|
|
54
|
+
properties: {
|
|
55
|
+
id: { type: 'string' },
|
|
56
|
+
name: { type: 'string', maxLength: 255 },
|
|
57
|
+
alg: { type: 'string', enum: ['hmac-sha256'] },
|
|
58
|
+
// value is write-only and never returned by the API.
|
|
59
|
+
// Provide it at deploy time via keyword replacement (e.g. ##HMAC_KEY_VALUE##).
|
|
60
|
+
// It is not exported and is omitted from exported configs.
|
|
61
|
+
value: { type: 'string' },
|
|
62
|
+
fingerprint: { type: 'string' },
|
|
63
|
+
},
|
|
64
|
+
additionalProperties: false,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
class NetworkACLKeysHandler extends default_1.default {
|
|
68
|
+
constructor(config) {
|
|
69
|
+
super({
|
|
70
|
+
...config,
|
|
71
|
+
type: 'networkACLKeys',
|
|
72
|
+
id: 'id',
|
|
73
|
+
identifiers: ['name'],
|
|
74
|
+
// value is write-only (never returned by API) and fingerprint/timestamps are
|
|
75
|
+
// API-generated — ignore all of them when computing dry-run diffs so keys
|
|
76
|
+
// with a local `value` don't show phantom UPDATEs.
|
|
77
|
+
ignoreDryRunFields: ['value', 'fingerprint', 'created_at', 'updated_at'],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
objString(key) {
|
|
81
|
+
return super.objString({ name: key.name, alg: key.alg });
|
|
82
|
+
}
|
|
83
|
+
async getType() {
|
|
84
|
+
if (this.existing)
|
|
85
|
+
return this.existing;
|
|
86
|
+
try {
|
|
87
|
+
// Not paginated — tenant cap is 10 keys. Returns { keys: [...] }.
|
|
88
|
+
const result = await this.client.keys.networkAcls.list();
|
|
89
|
+
this.existing = result.keys;
|
|
90
|
+
return this.existing;
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
if (err.statusCode === 404 || err.statusCode === 501) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
if (err.statusCode === 403) {
|
|
97
|
+
logger_1.default.debug('Network ACL key management is not enabled for this tenant. Please verify `scope` or contact Auth0 support.');
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
throw err;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async processChanges(assets) {
|
|
104
|
+
const { networkACLKeys } = assets;
|
|
105
|
+
// Do nothing if not set
|
|
106
|
+
if (!networkACLKeys)
|
|
107
|
+
return;
|
|
108
|
+
const { del, create } = await this.calcChanges(assets);
|
|
109
|
+
// Keys are immutable after creation — there is no update operation.
|
|
110
|
+
// A detected "update" (same name, different config) is a no-op: the existing key is kept as-is.
|
|
111
|
+
logger_1.default.debug(`Start processChanges for networkACLKeys [delete:${del.length}] [create:${create.length}]`);
|
|
112
|
+
await Promise.all([this.deleteNetworkACLKeys(del), this.createNetworkACLKeys(create)]);
|
|
113
|
+
}
|
|
114
|
+
async createNetworkACLKey(key) {
|
|
115
|
+
if (!key.value) {
|
|
116
|
+
logger_1.default.warn(`Skipping creation of Network ACL key "${key.name}": ` +
|
|
117
|
+
`'value' is required to create a key but is not present in the config. ` +
|
|
118
|
+
`Supply the key material via keyword replacement (e.g. ##HMAC_KEY_VALUE##) or create the key out-of-band.`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
await this.client.keys.networkAcls.create({
|
|
122
|
+
name: key.name,
|
|
123
|
+
alg: key.alg,
|
|
124
|
+
value: key.value,
|
|
125
|
+
});
|
|
126
|
+
this.didCreate(key);
|
|
127
|
+
this.created += 1;
|
|
128
|
+
}
|
|
129
|
+
async createNetworkACLKeys(creates) {
|
|
130
|
+
await this.client.pool
|
|
131
|
+
.addEachTask({
|
|
132
|
+
data: creates || [],
|
|
133
|
+
generator: (item) => this.createNetworkACLKey(item).catch((err) => {
|
|
134
|
+
throw new Error(`Problem creating ${this.type} ${this.objString(item)}\n${err}`);
|
|
135
|
+
}),
|
|
136
|
+
})
|
|
137
|
+
.promise();
|
|
138
|
+
}
|
|
139
|
+
async deleteNetworkACLKey(key) {
|
|
140
|
+
if (!key.id) {
|
|
141
|
+
throw new Error(`Missing id for ${this.type} ${this.objString(key)}`);
|
|
142
|
+
}
|
|
143
|
+
await this.client.keys.networkAcls.delete(key.id);
|
|
144
|
+
}
|
|
145
|
+
async deleteNetworkACLKeys(data) {
|
|
146
|
+
if (!data || data.length === 0)
|
|
147
|
+
return;
|
|
148
|
+
if (this.config('AUTH0_ALLOW_DELETE') === 'true' ||
|
|
149
|
+
this.config('AUTH0_ALLOW_DELETE') === true) {
|
|
150
|
+
await this.client.pool
|
|
151
|
+
.addEachTask({
|
|
152
|
+
data: data || [],
|
|
153
|
+
generator: (item) => this.deleteNetworkACLKey(item)
|
|
154
|
+
.then(() => {
|
|
155
|
+
this.didDelete(item);
|
|
156
|
+
this.deleted += 1;
|
|
157
|
+
})
|
|
158
|
+
.catch((err) => {
|
|
159
|
+
if (err.statusCode === 409) {
|
|
160
|
+
throw new Error(`Cannot delete Network ACL key "${item.name}" — it is still referenced by one or more ACL rules. ` +
|
|
161
|
+
`Remove the key reference from all ACL rules first.\n${err}`);
|
|
162
|
+
}
|
|
163
|
+
throw new Error(`Problem deleting ${this.type} ${this.objString(item)}\n${err}`);
|
|
164
|
+
}),
|
|
165
|
+
})
|
|
166
|
+
.promise();
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
logger_1.default.warn(`Detected the following ${this.type} should be deleted. Doing so may be destructive.\nYou can enable deletes by setting 'AUTH0_ALLOW_DELETE' to true in the config
|
|
170
|
+
\n${data.map((i) => this.objString(i)).join('\n')}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.default = NetworkACLKeysHandler;
|
|
175
|
+
__decorate([
|
|
176
|
+
(0, default_1.order)(60)
|
|
177
|
+
], NetworkACLKeysHandler.prototype, "processChanges", null);
|
|
@@ -21,7 +21,7 @@ export declare const schema: {
|
|
|
21
21
|
minimum: number;
|
|
22
22
|
};
|
|
23
23
|
rule: {
|
|
24
|
-
anyOf: {
|
|
24
|
+
anyOf: ({
|
|
25
25
|
type: string;
|
|
26
26
|
required: string[];
|
|
27
27
|
properties: {
|
|
@@ -171,6 +171,29 @@ export declare const schema: {
|
|
|
171
171
|
};
|
|
172
172
|
uniqueItems: boolean;
|
|
173
173
|
};
|
|
174
|
+
http_message_signature: {
|
|
175
|
+
type: string;
|
|
176
|
+
properties: {
|
|
177
|
+
keys: {
|
|
178
|
+
type: string;
|
|
179
|
+
minItems: number;
|
|
180
|
+
maxItems: number;
|
|
181
|
+
uniqueItems: boolean;
|
|
182
|
+
items: {
|
|
183
|
+
type: string;
|
|
184
|
+
properties: {
|
|
185
|
+
id: {
|
|
186
|
+
type: string;
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
required: string[];
|
|
190
|
+
additionalProperties: boolean;
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
required: string[];
|
|
195
|
+
additionalProperties: boolean;
|
|
196
|
+
};
|
|
174
197
|
};
|
|
175
198
|
additionalProperties: boolean;
|
|
176
199
|
};
|
|
@@ -271,6 +294,29 @@ export declare const schema: {
|
|
|
271
294
|
};
|
|
272
295
|
uniqueItems: boolean;
|
|
273
296
|
};
|
|
297
|
+
http_message_signature: {
|
|
298
|
+
type: string;
|
|
299
|
+
properties: {
|
|
300
|
+
keys: {
|
|
301
|
+
type: string;
|
|
302
|
+
minItems: number;
|
|
303
|
+
maxItems: number;
|
|
304
|
+
uniqueItems: boolean;
|
|
305
|
+
items: {
|
|
306
|
+
type: string;
|
|
307
|
+
properties: {
|
|
308
|
+
id: {
|
|
309
|
+
type: string;
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
required: string[];
|
|
313
|
+
additionalProperties: boolean;
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
};
|
|
317
|
+
required: string[];
|
|
318
|
+
additionalProperties: boolean;
|
|
319
|
+
};
|
|
274
320
|
};
|
|
275
321
|
additionalProperties: boolean;
|
|
276
322
|
};
|
|
@@ -278,9 +324,75 @@ export declare const schema: {
|
|
|
278
324
|
enum: string[];
|
|
279
325
|
type: string;
|
|
280
326
|
};
|
|
327
|
+
match_all?: undefined;
|
|
328
|
+
};
|
|
329
|
+
additionalProperties: boolean;
|
|
330
|
+
} | {
|
|
331
|
+
type: string;
|
|
332
|
+
required: string[];
|
|
333
|
+
properties: {
|
|
334
|
+
action: {
|
|
335
|
+
type: string;
|
|
336
|
+
anyOf: ({
|
|
337
|
+
type: string;
|
|
338
|
+
required: string[];
|
|
339
|
+
properties: {
|
|
340
|
+
block: {
|
|
341
|
+
type: string;
|
|
342
|
+
enum: boolean[];
|
|
343
|
+
};
|
|
344
|
+
};
|
|
345
|
+
additionalProperties: boolean;
|
|
346
|
+
} | {
|
|
347
|
+
type: string;
|
|
348
|
+
required: string[];
|
|
349
|
+
properties: {
|
|
350
|
+
allow: {
|
|
351
|
+
type: string;
|
|
352
|
+
enum: boolean[];
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
additionalProperties: boolean;
|
|
356
|
+
} | {
|
|
357
|
+
type: string;
|
|
358
|
+
required: string[];
|
|
359
|
+
properties: {
|
|
360
|
+
log: {
|
|
361
|
+
type: string;
|
|
362
|
+
enum: boolean[];
|
|
363
|
+
};
|
|
364
|
+
};
|
|
365
|
+
additionalProperties: boolean;
|
|
366
|
+
} | {
|
|
367
|
+
type: string;
|
|
368
|
+
required: string[];
|
|
369
|
+
properties: {
|
|
370
|
+
redirect: {
|
|
371
|
+
type: string;
|
|
372
|
+
enum: boolean[];
|
|
373
|
+
};
|
|
374
|
+
redirect_uri: {
|
|
375
|
+
type: string;
|
|
376
|
+
minLength: number;
|
|
377
|
+
maxLength: number;
|
|
378
|
+
};
|
|
379
|
+
};
|
|
380
|
+
additionalProperties: boolean;
|
|
381
|
+
})[];
|
|
382
|
+
};
|
|
383
|
+
match_all: {
|
|
384
|
+
type: string;
|
|
385
|
+
enum: boolean[];
|
|
386
|
+
};
|
|
387
|
+
scope: {
|
|
388
|
+
enum: string[];
|
|
389
|
+
type: string;
|
|
390
|
+
};
|
|
391
|
+
match?: undefined;
|
|
392
|
+
not_match?: undefined;
|
|
281
393
|
};
|
|
282
394
|
additionalProperties: boolean;
|
|
283
|
-
}[];
|
|
395
|
+
})[];
|
|
284
396
|
};
|
|
285
397
|
};
|
|
286
398
|
additionalProperties: boolean;
|
|
@@ -1,10 +1,49 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
2
41
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
42
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
43
|
};
|
|
5
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
45
|
exports.schema = void 0;
|
|
7
|
-
const default_1 =
|
|
46
|
+
const default_1 = __importStar(require("./default"));
|
|
8
47
|
const client_1 = require("../client");
|
|
9
48
|
const logger_1 = __importDefault(require("../../../logger"));
|
|
10
49
|
// Define action types
|
|
@@ -57,6 +96,15 @@ const RedirectAction = {
|
|
|
57
96
|
},
|
|
58
97
|
additionalProperties: false,
|
|
59
98
|
};
|
|
99
|
+
// Shared sub-schemas reused across every rule branch below.
|
|
100
|
+
const ActionSchema = {
|
|
101
|
+
type: 'object',
|
|
102
|
+
anyOf: [BlockAction, AllowAction, LogAction, RedirectAction],
|
|
103
|
+
};
|
|
104
|
+
const ScopeSchema = {
|
|
105
|
+
enum: ['management', 'authentication', 'tenant'],
|
|
106
|
+
type: 'string',
|
|
107
|
+
};
|
|
60
108
|
// Define MatchSchema
|
|
61
109
|
const MatchSchema = {
|
|
62
110
|
type: 'object',
|
|
@@ -155,6 +203,27 @@ const MatchSchema = {
|
|
|
155
203
|
},
|
|
156
204
|
uniqueItems: true,
|
|
157
205
|
},
|
|
206
|
+
http_message_signature: {
|
|
207
|
+
type: 'object',
|
|
208
|
+
properties: {
|
|
209
|
+
keys: {
|
|
210
|
+
type: 'array',
|
|
211
|
+
minItems: 1,
|
|
212
|
+
maxItems: 10,
|
|
213
|
+
uniqueItems: true,
|
|
214
|
+
items: {
|
|
215
|
+
type: 'object',
|
|
216
|
+
properties: {
|
|
217
|
+
id: { type: 'string' },
|
|
218
|
+
},
|
|
219
|
+
required: ['id'],
|
|
220
|
+
additionalProperties: false,
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
required: ['keys'],
|
|
225
|
+
additionalProperties: false,
|
|
226
|
+
},
|
|
158
227
|
},
|
|
159
228
|
additionalProperties: false,
|
|
160
229
|
};
|
|
@@ -182,16 +251,10 @@ exports.schema = {
|
|
|
182
251
|
type: 'object',
|
|
183
252
|
required: ['action', 'scope', 'match'],
|
|
184
253
|
properties: {
|
|
185
|
-
action:
|
|
186
|
-
type: 'object',
|
|
187
|
-
anyOf: [BlockAction, AllowAction, LogAction, RedirectAction],
|
|
188
|
-
},
|
|
254
|
+
action: ActionSchema,
|
|
189
255
|
match: MatchSchema,
|
|
190
256
|
not_match: MatchSchema,
|
|
191
|
-
scope:
|
|
192
|
-
enum: ['management', 'authentication', 'tenant'],
|
|
193
|
-
type: 'string',
|
|
194
|
-
},
|
|
257
|
+
scope: ScopeSchema,
|
|
195
258
|
},
|
|
196
259
|
additionalProperties: false,
|
|
197
260
|
},
|
|
@@ -199,16 +262,25 @@ exports.schema = {
|
|
|
199
262
|
type: 'object',
|
|
200
263
|
required: ['action', 'scope', 'not_match'],
|
|
201
264
|
properties: {
|
|
202
|
-
action:
|
|
203
|
-
type: 'object',
|
|
204
|
-
anyOf: [BlockAction, AllowAction, LogAction, RedirectAction],
|
|
205
|
-
},
|
|
265
|
+
action: ActionSchema,
|
|
206
266
|
not_match: MatchSchema,
|
|
207
267
|
match: MatchSchema,
|
|
208
|
-
scope:
|
|
209
|
-
|
|
210
|
-
|
|
268
|
+
scope: ScopeSchema,
|
|
269
|
+
},
|
|
270
|
+
additionalProperties: false,
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
// Unconditional match: `match_all` is mutually exclusive with `match`/`not_match`.
|
|
274
|
+
type: 'object',
|
|
275
|
+
required: ['action', 'scope', 'match_all'],
|
|
276
|
+
properties: {
|
|
277
|
+
action: ActionSchema,
|
|
278
|
+
match_all: {
|
|
279
|
+
// Schema only permits `true`; omit the property instead of sending `false`.
|
|
280
|
+
type: 'boolean',
|
|
281
|
+
enum: [true],
|
|
211
282
|
},
|
|
283
|
+
scope: ScopeSchema,
|
|
212
284
|
},
|
|
213
285
|
additionalProperties: false,
|
|
214
286
|
},
|
|
@@ -355,3 +427,6 @@ class NetworkACLsHandler extends default_1.default {
|
|
|
355
427
|
}
|
|
356
428
|
}
|
|
357
429
|
exports.default = NetworkACLsHandler;
|
|
430
|
+
__decorate([
|
|
431
|
+
(0, default_1.order)(65)
|
|
432
|
+
], NetworkACLsHandler.prototype, "processChanges", null);
|
|
@@ -51,6 +51,12 @@ const logger_1 = __importDefault(require("../../../logger"));
|
|
|
51
51
|
const client_1 = require("../client");
|
|
52
52
|
const utils_1 = require("../../../utils");
|
|
53
53
|
const utils_2 = require("../../utils");
|
|
54
|
+
// Org sub-resources are skipped when the tenant can't read them: the EA feature is off
|
|
55
|
+
// (feature_not_enabled, returned as 400 or 403) or the token lacks scope (403). The SDK
|
|
56
|
+
// puts the API code on `err.body.errorCode`, not `err.errorCode`.
|
|
57
|
+
function isOrgSubresourceUnavailable(err) {
|
|
58
|
+
return err?.statusCode === 403 || err?.body?.errorCode === 'feature_not_enabled';
|
|
59
|
+
}
|
|
54
60
|
exports.schema = {
|
|
55
61
|
type: 'array',
|
|
56
62
|
items: {
|
|
@@ -618,8 +624,8 @@ class OrganizationsHandler extends default_1.default {
|
|
|
618
624
|
if (err.statusCode === 404 || err.statusCode === 501) {
|
|
619
625
|
return null;
|
|
620
626
|
}
|
|
621
|
-
if (err
|
|
622
|
-
logger_1.default.debug(
|
|
627
|
+
if (isOrgSubresourceUnavailable(err)) {
|
|
628
|
+
logger_1.default.debug(`Skipping organization discovery domains (${err?.body?.errorCode ?? err.statusCode}).`);
|
|
623
629
|
return null;
|
|
624
630
|
}
|
|
625
631
|
throw err;
|
|
@@ -664,8 +670,8 @@ class OrganizationsHandler extends default_1.default {
|
|
|
664
670
|
if (err.statusCode === 404 || err.statusCode === 501) {
|
|
665
671
|
return null;
|
|
666
672
|
}
|
|
667
|
-
if (err
|
|
668
|
-
logger_1.default.debug(
|
|
673
|
+
if (isOrgSubresourceUnavailable(err)) {
|
|
674
|
+
logger_1.default.debug(`Skipping org-client associations (${err?.body?.errorCode ?? err.statusCode}).`);
|
|
669
675
|
return null;
|
|
670
676
|
}
|
|
671
677
|
throw err;
|
package/lib/tools/constants.d.ts
CHANGED
|
@@ -86,6 +86,7 @@ declare const constants: {
|
|
|
86
86
|
FLOWS_VAULT_DIRECTORY: string;
|
|
87
87
|
SELF_SERVICE_PROFILE_DIRECTORY: string;
|
|
88
88
|
NETWORK_ACLS_DIRECTORY: string;
|
|
89
|
+
NETWORK_ACL_KEYS_DIRECTORY: string;
|
|
89
90
|
USER_ATTRIBUTE_PROFILES_DIRECTORY: string;
|
|
90
91
|
CONNECTION_PROFILES_DIRECTORY: string;
|
|
91
92
|
TOKEN_EXCHANGE_PROFILES_DIRECTORY: string;
|
package/lib/tools/constants.js
CHANGED
|
@@ -216,6 +216,7 @@ const constants = {
|
|
|
216
216
|
FLOWS_VAULT_DIRECTORY: 'flow-vault-connections',
|
|
217
217
|
SELF_SERVICE_PROFILE_DIRECTORY: 'self-service-profiles',
|
|
218
218
|
NETWORK_ACLS_DIRECTORY: 'network-acls',
|
|
219
|
+
NETWORK_ACL_KEYS_DIRECTORY: 'network-acl-keys',
|
|
219
220
|
USER_ATTRIBUTE_PROFILES_DIRECTORY: 'user-attribute-profiles',
|
|
220
221
|
CONNECTION_PROFILES_DIRECTORY: 'connection-profiles',
|
|
221
222
|
TOKEN_EXCHANGE_PROFILES_DIRECTORY: 'token-exchange-profiles',
|
package/lib/types.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { SsProfileWithCustomText } from './tools/auth0/handlers/selfServiceProfi
|
|
|
16
16
|
import { PhoneProvider } from './tools/auth0/handlers/phoneProvider';
|
|
17
17
|
import { PhoneTemplate } from './tools/auth0/handlers/phoneTemplates';
|
|
18
18
|
import { NetworkACL } from './tools/auth0/handlers/networkACLs';
|
|
19
|
+
import { NetworkAclKey } from './tools/auth0/handlers/networkACLKeys';
|
|
19
20
|
import { UserAttributeProfile } from './tools/auth0/handlers/userAttributeProfiles';
|
|
20
21
|
import { AttackProtection } from './tools/auth0/handlers/attackProtection';
|
|
21
22
|
import { TokenExchangeProfile } from './tools/auth0/handlers/tokenExchangeProfiles';
|
|
@@ -156,6 +157,7 @@ export type Assets = Partial<{
|
|
|
156
157
|
flows: Flow[] | null;
|
|
157
158
|
flowVaultConnections: FlowVaultConnection[] | null;
|
|
158
159
|
selfServiceProfiles: SsProfileWithCustomText[] | null;
|
|
160
|
+
networkACLKeys: NetworkAclKey[] | null;
|
|
159
161
|
networkACLs: NetworkACL[] | null;
|
|
160
162
|
userAttributeProfiles: UserAttributeProfile[] | null;
|
|
161
163
|
userAttributeProfilesWithId: UserAttributeProfile[] | null;
|
|
@@ -183,7 +185,7 @@ export type DetailedDryRunChanges = {
|
|
|
183
185
|
changes: DetailedDryRunChange[];
|
|
184
186
|
};
|
|
185
187
|
};
|
|
186
|
-
export type AssetTypes = 'rules' | 'rulesConfigs' | 'hooks' | 'pages' | 'databases' | 'clientGrants' | 'resourceServers' | 'clients' | 'connections' | 'tenant' | 'emailProvider' | 'emailTemplates' | 'guardianFactors' | 'guardianFactorProviders' | 'guardianFactorTemplates' | 'guardianPhoneFactorMessageTypes' | 'guardianPhoneFactorSelectedProvider' | 'guardianPolicies' | 'roles' | 'actions' | 'actionModules' | 'organizations' | 'triggers' | 'attackProtection' | 'riskAssessment' | 'branding' | 'phoneProviders' | 'phoneTemplates' | 'logStreams' | 'prompts' | 'customDomains' | 'themes' | 'forms' | 'flows' | 'flowVaultConnections' | 'selfServiceProfiles' | 'networkACLs' | 'userAttributeProfiles' | 'connectionProfiles' | 'tokenExchangeProfiles' | 'supplementalSignals' | 'rateLimitPolicies' | 'eventStreams' | 'clientAuthCredentials';
|
|
188
|
+
export type AssetTypes = 'rules' | 'rulesConfigs' | 'hooks' | 'pages' | 'databases' | 'clientGrants' | 'resourceServers' | 'clients' | 'connections' | 'tenant' | 'emailProvider' | 'emailTemplates' | 'guardianFactors' | 'guardianFactorProviders' | 'guardianFactorTemplates' | 'guardianPhoneFactorMessageTypes' | 'guardianPhoneFactorSelectedProvider' | 'guardianPolicies' | 'roles' | 'actions' | 'actionModules' | 'organizations' | 'triggers' | 'attackProtection' | 'riskAssessment' | 'branding' | 'phoneProviders' | 'phoneTemplates' | 'logStreams' | 'prompts' | 'customDomains' | 'themes' | 'forms' | 'flows' | 'flowVaultConnections' | 'selfServiceProfiles' | 'networkACLKeys' | 'networkACLs' | 'userAttributeProfiles' | 'connectionProfiles' | 'tokenExchangeProfiles' | 'supplementalSignals' | 'rateLimitPolicies' | 'eventStreams' | 'clientAuthCredentials';
|
|
187
189
|
export type KeywordMappings = {
|
|
188
190
|
[key: string]: (string | number)[] | string | number;
|
|
189
191
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auth0-deploy-cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.45.0",
|
|
4
4
|
"description": "A command line tool for deploying updates to your Auth0 tenant",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@clack/prompts": "1.4.0",
|
|
37
37
|
"ajv": "^6.12.6",
|
|
38
|
-
"auth0": "^6.
|
|
38
|
+
"auth0": "^6.4.0",
|
|
39
39
|
"chalk": "5.6.2",
|
|
40
40
|
"dot-prop": "^5.3.0",
|
|
41
41
|
"fs-extra": "^10.1.0",
|