auth0-deploy-cli 8.43.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 +53 -1
- package/README.md +1 -1
- package/lib/context/defaults.d.ts +7 -0
- package/lib/context/defaults.js +74 -30
- package/lib/context/directory/handlers/attackProtection.js +1 -1
- package/lib/context/directory/handlers/branding.js +9 -1
- package/lib/context/directory/handlers/clients.js +9 -3
- package/lib/context/directory/handlers/connections.js +10 -4
- package/lib/context/directory/handlers/emailTemplates.js +9 -0
- 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/directory/handlers/prompts.js +11 -3
- package/lib/context/yaml/handlers/attackProtection.js +1 -1
- package/lib/context/yaml/handlers/branding.js +8 -1
- package/lib/context/yaml/handlers/clients.js +4 -1
- package/lib/context/yaml/handlers/connections.js +3 -1
- package/lib/context/yaml/handlers/flows.js +7 -0
- package/lib/context/yaml/handlers/forms.js +7 -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/context/yaml/handlers/prompts.js +7 -1
- package/lib/keywordPreservation.d.ts +1 -1
- package/lib/keywordPreservation.js +2 -1
- package/lib/readonly.js +5 -0
- package/lib/tools/auth0/handlers/attackProtection.js +3 -1
- package/lib/tools/auth0/handlers/clients.d.ts +40 -0
- package/lib/tools/auth0/handlers/clients.js +58 -1
- package/lib/tools/auth0/handlers/connectionProfiles.d.ts +27 -0
- package/lib/tools/auth0/handlers/connectionProfiles.js +30 -0
- package/lib/tools/auth0/handlers/connections.js +10 -3
- package/lib/tools/auth0/handlers/databases.d.ts +28 -0
- package/lib/tools/auth0/handlers/databases.js +47 -22
- package/lib/tools/auth0/handlers/default.d.ts +23 -0
- package/lib/tools/auth0/handlers/default.js +21 -10
- 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.d.ts +1 -1
- package/lib/tools/auth0/handlers/organizations.js +49 -20
- package/lib/tools/auth0/handlers/phoneProvider.js +10 -2
- package/lib/tools/calculateDryRunChanges.js +12 -8
- package/lib/tools/constants.d.ts +1 -0
- package/lib/tools/constants.js +1 -0
- package/lib/types.d.ts +3 -1
- package/lib/utils.js +5 -2
- package/package.json +2 -2
|
@@ -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);
|
|
@@ -147,7 +147,7 @@ export default class OrganizationsHandler extends DefaultHandler {
|
|
|
147
147
|
createOrganizations(creates: CalculatedChanges['create']): Promise<void>;
|
|
148
148
|
updateOrganization(org: any, organizations: any): Promise<{
|
|
149
149
|
id: any;
|
|
150
|
-
}>;
|
|
150
|
+
} | null>;
|
|
151
151
|
getClientGrantIDByClientName(clientsName: string): string;
|
|
152
152
|
getClientIdByClientName(clientName: string): string;
|
|
153
153
|
getFormattedClientGrants(): Promise<FormattedClientGrants[]>;
|
|
@@ -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: {
|
|
@@ -194,8 +200,9 @@ class OrganizationsHandler extends default_1.default {
|
|
|
194
200
|
throw new Error(`Organization "${organization.name}" was created but the response did not include an ID. Skipping connection/grant association.`);
|
|
195
201
|
}
|
|
196
202
|
const createdId = created.id;
|
|
203
|
+
const retryConfig = this.getRetryConfig();
|
|
197
204
|
if (typeof org.connections !== 'undefined' && org.connections.length > 0) {
|
|
198
|
-
await Promise.all(org.connections.map((conn) => this.client.organizations.connections.create(createdId, conn)));
|
|
205
|
+
await Promise.all(org.connections.map((conn) => (0, default_1.retryWithExponentialBackoff)(() => this.client.organizations.connections.create(createdId, conn), retryConfig)));
|
|
199
206
|
}
|
|
200
207
|
if (typeof org.client_grants !== 'undefined' && org.client_grants.length > 0) {
|
|
201
208
|
await Promise.all(org.client_grants.map((organizationClientGrants) => this.createOrganizationClientGrants(createdId, this.getClientGrantIDByClientName(organizationClientGrants.client_id))));
|
|
@@ -240,7 +247,8 @@ class OrganizationsHandler extends default_1.default {
|
|
|
240
247
|
.promise();
|
|
241
248
|
}
|
|
242
249
|
async updateOrganization(org, organizations) {
|
|
243
|
-
const
|
|
250
|
+
const existingOrg = organizations.find((orgToUpdate) => orgToUpdate.name === org.name);
|
|
251
|
+
const { connections: existingConnections, client_grants: existingClientGrants, discovery_domains: existingDiscoveryDomains, clients: existingOrgClients = [], } = existingOrg;
|
|
244
252
|
const params = { id: org.id };
|
|
245
253
|
const { connections, client_grants: organizationClientGrants, discovery_domains: organizationDiscoveryDomains, clients: organizationClients, } = org;
|
|
246
254
|
delete org.connections;
|
|
@@ -249,7 +257,14 @@ class OrganizationsHandler extends default_1.default {
|
|
|
249
257
|
delete org.client_grants;
|
|
250
258
|
delete org.discovery_domains;
|
|
251
259
|
delete org.clients;
|
|
252
|
-
|
|
260
|
+
// Only PATCH if top-level properties actually differ from the existing state.
|
|
261
|
+
// Compare only the keys present in the desired config against those same keys
|
|
262
|
+
// on the remote org, so that fields the user didn't specify are not considered.
|
|
263
|
+
let changed = false;
|
|
264
|
+
if (!(0, lodash_1.isEqual)(org, (0, lodash_1.pick)(existingOrg, Object.keys(org)))) {
|
|
265
|
+
await this.client.organizations.update(params.id, org);
|
|
266
|
+
changed = true;
|
|
267
|
+
}
|
|
253
268
|
// organization connections
|
|
254
269
|
const connectionsToRemove = existingConnections.filter((c) => !connections.find((x) => x.connection_id === c.connection_id));
|
|
255
270
|
const connectionsToAdd = connections.filter((c) => !existingConnections.find((x) => x.connection_id === c.connection_id));
|
|
@@ -260,27 +275,27 @@ class OrganizationsHandler extends default_1.default {
|
|
|
260
275
|
x.organization_access_level !== c.organization_access_level ||
|
|
261
276
|
x.organization_connection_name !== c.organization_connection_name ||
|
|
262
277
|
x.is_enabled !== (c.is_enabled ?? true))));
|
|
278
|
+
if (connectionsToUpdate.length > 0 ||
|
|
279
|
+
connectionsToAdd.length > 0 ||
|
|
280
|
+
connectionsToRemove.length > 0) {
|
|
281
|
+
changed = true;
|
|
282
|
+
}
|
|
283
|
+
const retryConfig = this.getRetryConfig();
|
|
263
284
|
// Handle updates first
|
|
264
|
-
await Promise.all(connectionsToUpdate.map((conn) => this.client.organizations.connections
|
|
265
|
-
.update(params.id, conn.connection_id, {
|
|
285
|
+
await Promise.all(connectionsToUpdate.map((conn) => (0, default_1.retryWithExponentialBackoff)(() => this.client.organizations.connections.update(params.id, conn.connection_id, {
|
|
266
286
|
organization_connection_name: conn.organization_connection_name,
|
|
267
287
|
assign_membership_on_login: conn.assign_membership_on_login,
|
|
268
288
|
show_as_button: conn.show_as_button,
|
|
269
289
|
is_signup_enabled: conn.is_signup_enabled,
|
|
270
290
|
is_enabled: conn.is_enabled,
|
|
271
291
|
organization_access_level: conn.organization_access_level,
|
|
272
|
-
})
|
|
273
|
-
.catch(() => {
|
|
292
|
+
}), retryConfig).catch(() => {
|
|
274
293
|
throw new Error(`Problem updating Enabled Connection ${conn.connection_id} for organizations ${params.id}`);
|
|
275
294
|
})));
|
|
276
|
-
await Promise.all(connectionsToAdd.map((conn) => this.client.organizations.connections
|
|
277
|
-
.create(params.id, (0, lodash_1.omit)(conn, 'connection'))
|
|
278
|
-
.catch(() => {
|
|
295
|
+
await Promise.all(connectionsToAdd.map((conn) => (0, default_1.retryWithExponentialBackoff)(() => this.client.organizations.connections.create(params.id, (0, lodash_1.omit)(conn, 'connection')), retryConfig).catch(() => {
|
|
279
296
|
throw new Error(`Problem adding Enabled Connection ${conn.connection_id} for organizations ${params.id}`);
|
|
280
297
|
})));
|
|
281
|
-
await Promise.all(connectionsToRemove.map((conn) => this.client.organizations.connections
|
|
282
|
-
.delete(params.id, conn.connection_id)
|
|
283
|
-
.catch(() => {
|
|
298
|
+
await Promise.all(connectionsToRemove.map((conn) => (0, default_1.retryWithExponentialBackoff)(() => this.client.organizations.connections.delete(params.id, conn.connection_id), retryConfig).catch(() => {
|
|
284
299
|
throw new Error(`Problem removing Enabled Connection ${conn.connection_id} for organizations ${params.id}`);
|
|
285
300
|
})));
|
|
286
301
|
// organization client_grants
|
|
@@ -294,6 +309,9 @@ class OrganizationsHandler extends default_1.default {
|
|
|
294
309
|
?.map((clientGrant) => ({
|
|
295
310
|
grant_id: this.getClientGrantIDByClientName(clientGrant.client_id),
|
|
296
311
|
})) || [];
|
|
312
|
+
if (orgClientGrantsToAdd.length > 0 || orgClientGrantsToRemove.length > 0) {
|
|
313
|
+
changed = true;
|
|
314
|
+
}
|
|
297
315
|
// Handle updates first
|
|
298
316
|
await Promise.all(orgClientGrantsToAdd.map((orgClientGrant) => this.createOrganizationClientGrants(params.id, orgClientGrant.grant_id).catch(() => {
|
|
299
317
|
throw new Error(`Problem adding organization clientGrant ${orgClientGrant.grant_id} for organizations ${params.id}`);
|
|
@@ -315,6 +333,9 @@ class OrganizationsHandler extends default_1.default {
|
|
|
315
333
|
};
|
|
316
334
|
})
|
|
317
335
|
.filter(Boolean) || [];
|
|
336
|
+
if (orgDiscoveryDomainsToUpdate.length > 0 || orgDiscoveryDomainsToAdd.length > 0) {
|
|
337
|
+
changed = true;
|
|
338
|
+
}
|
|
318
339
|
for (const { id, domain, ...updateParams } of orgDiscoveryDomainsToUpdate) {
|
|
319
340
|
try {
|
|
320
341
|
await this.updateOrganizationDiscoveryDomain(params.id, id, domain, updateParams);
|
|
@@ -338,6 +359,7 @@ class OrganizationsHandler extends default_1.default {
|
|
|
338
359
|
if (orgDiscoveryDomainsToRemove.length > 0) {
|
|
339
360
|
if (this.config('AUTH0_ALLOW_DELETE') === 'true' ||
|
|
340
361
|
this.config('AUTH0_ALLOW_DELETE') === true) {
|
|
362
|
+
changed = true;
|
|
341
363
|
for (const domain of orgDiscoveryDomainsToRemove) {
|
|
342
364
|
try {
|
|
343
365
|
await this.deleteOrganizationDiscoveryDomain(params.id, domain.domain, domain.id);
|
|
@@ -375,6 +397,7 @@ class OrganizationsHandler extends default_1.default {
|
|
|
375
397
|
}))
|
|
376
398
|
.filter((oc) => !!oc.client_id);
|
|
377
399
|
if (orgClientsToAdd.length > 0) {
|
|
400
|
+
changed = true;
|
|
378
401
|
await this.createOrganizationClients(params.id, orgClientsToAdd).catch((err) => {
|
|
379
402
|
throw new Error(`Problem adding org clients for organization ${params.id}\n${err}`);
|
|
380
403
|
});
|
|
@@ -382,6 +405,7 @@ class OrganizationsHandler extends default_1.default {
|
|
|
382
405
|
if (orgClientsToRemove.length > 0) {
|
|
383
406
|
if (this.config('AUTH0_ALLOW_DELETE') === 'true' ||
|
|
384
407
|
this.config('AUTH0_ALLOW_DELETE') === true) {
|
|
408
|
+
changed = true;
|
|
385
409
|
await this.deleteOrganizationClients(params.id, orgClientsToRemove).catch((err) => {
|
|
386
410
|
throw new Error(`Problem removing org clients for organization ${params.id}\n${err}`);
|
|
387
411
|
});
|
|
@@ -390,6 +414,9 @@ class OrganizationsHandler extends default_1.default {
|
|
|
390
414
|
logger_1.default.warn(`Detected the following organization client associations should be removed. Doing so may be destructive.\nYou can enable deletes by setting 'AUTH0_ALLOW_DELETE' to true in the config\n${orgClientsToRemove.join('\n')}`);
|
|
391
415
|
}
|
|
392
416
|
}
|
|
417
|
+
if (orgClientsToUpdate.length > 0) {
|
|
418
|
+
changed = true;
|
|
419
|
+
}
|
|
393
420
|
await Promise.all(orgClientsToUpdate.map((oc) => this.client.organizations.clients
|
|
394
421
|
.update(params.id, oc.client_id, {
|
|
395
422
|
use_for_member_access: oc.use_for_member_access,
|
|
@@ -397,7 +424,7 @@ class OrganizationsHandler extends default_1.default {
|
|
|
397
424
|
.catch((err) => {
|
|
398
425
|
throw new Error(`Problem updating org client ${oc.client_id} for organization ${params.id}\n${err}`);
|
|
399
426
|
})));
|
|
400
|
-
return params;
|
|
427
|
+
return changed ? params : null;
|
|
401
428
|
}
|
|
402
429
|
getClientGrantIDByClientName(clientsName) {
|
|
403
430
|
const found = this.formattedClientGrants.find((c) => c.client_id === clientsName);
|
|
@@ -435,8 +462,10 @@ class OrganizationsHandler extends default_1.default {
|
|
|
435
462
|
data: updates || [],
|
|
436
463
|
generator: (item) => this.updateOrganization(item, orgs)
|
|
437
464
|
.then((data) => {
|
|
438
|
-
|
|
439
|
-
|
|
465
|
+
if (data) {
|
|
466
|
+
this.didUpdate(data);
|
|
467
|
+
this.updated += 1;
|
|
468
|
+
}
|
|
440
469
|
})
|
|
441
470
|
.catch((err) => {
|
|
442
471
|
throw new Error(`Problem updating ${this.type} ${this.objString(item)}\n${err}`);
|
|
@@ -595,8 +624,8 @@ class OrganizationsHandler extends default_1.default {
|
|
|
595
624
|
if (err.statusCode === 404 || err.statusCode === 501) {
|
|
596
625
|
return null;
|
|
597
626
|
}
|
|
598
|
-
if (err
|
|
599
|
-
logger_1.default.debug(
|
|
627
|
+
if (isOrgSubresourceUnavailable(err)) {
|
|
628
|
+
logger_1.default.debug(`Skipping organization discovery domains (${err?.body?.errorCode ?? err.statusCode}).`);
|
|
600
629
|
return null;
|
|
601
630
|
}
|
|
602
631
|
throw err;
|
|
@@ -641,8 +670,8 @@ class OrganizationsHandler extends default_1.default {
|
|
|
641
670
|
if (err.statusCode === 404 || err.statusCode === 501) {
|
|
642
671
|
return null;
|
|
643
672
|
}
|
|
644
|
-
if (err
|
|
645
|
-
logger_1.default.debug(
|
|
673
|
+
if (isOrgSubresourceUnavailable(err)) {
|
|
674
|
+
logger_1.default.debug(`Skipping org-client associations (${err?.body?.errorCode ?? err.statusCode}).`);
|
|
646
675
|
return null;
|
|
647
676
|
}
|
|
648
677
|
throw err;
|