auth0-deploy-cli 7.7.0 → 7.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [7.7.1] - 2022-04-07
11
+
12
+ ### Added
13
+
14
+ - Deprecation warnings for now deprecated asset-specific exclusion configuration properties: `AUTH0_EXCLUDED_RULES`, `AUTH0_EXCLUDED_CLIENTS`, `AUTH0_EXCLUDED_DATABASES`, `AUTH0_EXCLUDED_CONNECTIONS`, `AUTH0_EXCLUDED_RESOURCE_SERVERS`, `AUTH0_EXCLUDED_DEFAULTS`. See [Resource Exclusion Proposal](https://github.com/auth0/auth0-deploy-cli/issues/451#user-content-deprecated-exclusion-props) for details. [#481]
15
+
16
+ ### Fixed
17
+
18
+ - Rules configs failing to update after regression prevented asset-specific overrides of Node Auth0 SDK methods [#482]
19
+ - Attack protection not replacing keywords [#478]
20
+
10
21
  ## [7.7.0] - 2022-04-06
11
22
 
12
23
  ### Added
@@ -652,7 +663,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
652
663
  [#453]: https://github.com/auth0/auth0-deploy-cli/issues/453
653
664
  [#468]: https://github.com/auth0/auth0-deploy-cli/issues/468
654
665
  [#471]: https://github.com/auth0/auth0-deploy-cli/issues/471
655
- [unreleased]: https://github.com/auth0/auth0-deploy-cli/compare/v7.7.0...HEAD
666
+ [#478]: https://github.com/auth0/auth0-deploy-cli/issues/478
667
+ [#481]: https://github.com/auth0/auth0-deploy-cli/issues/481
668
+ [#482]: https://github.com/auth0/auth0-deploy-cli/issues/482
669
+ [unreleased]: https://github.com/auth0/auth0-deploy-cli/compare/v7.7.1...HEAD
670
+ [7.7.1]: https://github.com/auth0/auth0-deploy-cli/compare/v7.7.0...v7.7.1
656
671
  [7.7.0]: https://github.com/auth0/auth0-deploy-cli/compare/v7.6.0...v7.7.0
657
672
  [7.6.0]: https://github.com/auth0/auth0-deploy-cli/compare/v7.5.2...v7.6.0
658
673
  [7.5.2]: https://github.com/auth0/auth0-deploy-cli/compare/v7.5.1...v7.5.2
@@ -32,9 +32,9 @@ function parse(context) {
32
32
  attackProtection: undefined,
33
33
  };
34
34
  }
35
- const breachedPasswordDetection = (0, utils_1.loadJSON)(files.breachedPasswordDetection);
36
- const bruteForceProtection = (0, utils_1.loadJSON)(files.bruteForceProtection);
37
- const suspiciousIpThrottling = (0, utils_1.loadJSON)(files.suspiciousIpThrottling);
35
+ const breachedPasswordDetection = (0, utils_1.loadJSON)(files.breachedPasswordDetection, context.mappings);
36
+ const bruteForceProtection = (0, utils_1.loadJSON)(files.bruteForceProtection, context.mappings);
37
+ const suspiciousIpThrottling = (0, utils_1.loadJSON)(files.suspiciousIpThrottling, context.mappings);
38
38
  return {
39
39
  attackProtection: {
40
40
  breachedPasswordDetection,
@@ -46,6 +46,24 @@ const setupContext = (config) => __awaiter(void 0, void 0, void 0, function* ()
46
46
  if (missingParams.length > 0) {
47
47
  throw new Error(`The following parameters were missing. Please add them to your config.json or as an environment variable. ${JSON.stringify(missingParams)}`);
48
48
  }
49
+ ((config) => {
50
+ // Detect and warn on usage of deprecated exclusion params. See: https://github.com/auth0/auth0-deploy-cli/issues/451#user-content-deprecated-exclusion-props
51
+ const deprecatedExclusionParams = [
52
+ 'AUTH0_EXCLUDED_RULES',
53
+ 'AUTH0_EXCLUDED_CLIENTS',
54
+ 'AUTH0_EXCLUDED_DATABASES',
55
+ 'AUTH0_EXCLUDED_CONNECTIONS',
56
+ 'AUTH0_EXCLUDED_RESOURCE_SERVERS',
57
+ 'AUTH0_EXCLUDED_DEFAULTS',
58
+ ];
59
+ const usedDeprecatedParams = deprecatedExclusionParams.filter((deprecatedParam) => {
60
+ const deprecatedConfigValue = config[deprecatedParam];
61
+ return !!deprecatedConfigValue && deprecatedConfigValue.length > 0;
62
+ });
63
+ if (usedDeprecatedParams.length > 0) {
64
+ 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.`);
65
+ }
66
+ })(config);
49
67
  const accessToken = yield (() => __awaiter(void 0, void 0, void 0, function* () {
50
68
  if (!!config.AUTH0_ACCESS_TOKEN)
51
69
  return config.AUTH0_ACCESS_TOKEN;
@@ -33,7 +33,7 @@ const API_FREQUENCY_PER_SECOND = 8;
33
33
  const MAX_PAGE_SIZE = 100;
34
34
  function getEntity(rsp) {
35
35
  const found = Object.values(rsp).filter((a) => Array.isArray(a));
36
- if (found.length === 1) {
36
+ if (Array.isArray(found) && found.length === 1) {
37
37
  return found[0];
38
38
  }
39
39
  throw new Error('There was an error trying to find the entity within paginate');
@@ -147,11 +147,11 @@ function pagedManager(client, manager) {
147
147
  }
148
148
  // Warp around the ManagementClient and detect when requesting specific pages to return all
149
149
  function pagedClient(client) {
150
- client.pool = new promise_pool_executor_1.PromisePoolExecutor({
151
- concurrencyLimit: API_CONCURRENCY,
152
- frequencyLimit: API_FREQUENCY_PER_SECOND,
153
- frequencyWindow: 1000, // 1 sec
154
- });
155
- return pagedManager(client, client);
150
+ const clientWithPooling = Object.assign(Object.assign({}, client), { pool: new promise_pool_executor_1.PromisePoolExecutor({
151
+ concurrencyLimit: API_CONCURRENCY,
152
+ frequencyLimit: API_FREQUENCY_PER_SECOND,
153
+ frequencyWindow: 1000, // 1 sec
154
+ }) });
155
+ return pagedManager(clientWithPooling, clientWithPooling);
156
156
  }
157
157
  exports.default = pagedClient;
@@ -111,14 +111,14 @@ class DatabaseHandler extends default_1.default {
111
111
  };
112
112
  // Convert enabled_clients by name to the id
113
113
  const clients = yield this.client.clients.getAll({ paginate: true, include_totals: true });
114
- const existingDatabasesConecctions = yield this.client.connections.getAll({
114
+ const existingDatabasesConnections = yield this.client.connections.getAll({
115
115
  strategy: 'auth0',
116
116
  paginate: true,
117
117
  include_totals: true,
118
118
  });
119
119
  const formatted = databases.map((db) => {
120
120
  if (db.enabled_clients) {
121
- return Object.assign(Object.assign({}, db), { enabled_clients: (0, utils_1.getEnabledClients)(assets, db, existingDatabasesConecctions, clients) });
121
+ return Object.assign(Object.assign({}, db), { enabled_clients: (0, utils_1.getEnabledClients)(assets, db, existingDatabasesConnections, clients) });
122
122
  }
123
123
  return db;
124
124
  });
@@ -56,7 +56,7 @@ class APIHandler {
56
56
  logger_1.default.info(`Updated [${this.type}]: ${this.objString(item)}`);
57
57
  }
58
58
  objString(item) {
59
- return (0, utils_1.dumpJSON)(item);
59
+ return (0, utils_1.convertJsonToString)(item);
60
60
  }
61
61
  getType() {
62
62
  return __awaiter(this, void 0, void 0, function* () {
@@ -106,7 +106,7 @@ class APIHandler {
106
106
  if (duplicateNames.length > 0) {
107
107
  const formatted = duplicateNames.map((dups) => dups.map((d) => `${d.name}`));
108
108
  throw new validationError_1.default(`There are multiple ${this.type} with the same name combinations
109
- ${(0, utils_1.dumpJSON)(formatted)}.
109
+ ${(0, utils_1.convertJsonToString)(formatted)}.
110
110
  Names must be unique.`);
111
111
  }
112
112
  // Do not allow items with same id
@@ -114,7 +114,7 @@ class APIHandler {
114
114
  if (duplicateIDs.length > 0) {
115
115
  const formatted = duplicateIDs.map((dups) => dups.map((d) => `${d[this.id]}`));
116
116
  throw new validationError_1.default(`There are multiple ${this.type} for the following stage-order combinations
117
- ${(0, utils_1.dumpJSON)(formatted)}.
117
+ ${(0, utils_1.convertJsonToString)(formatted)}.
118
118
  Only one rule must be defined for the same order number in a stage.`);
119
119
  }
120
120
  });
@@ -145,7 +145,7 @@ class APIHandler {
145
145
  .addEachTask({
146
146
  data: del || [],
147
147
  generator: (delItem) => {
148
- const delFunction = this.getClientFN('delete');
148
+ const delFunction = this.getClientFN(this.functions.delete);
149
149
  return delFunction({ [this.id]: delItem[this.id] })
150
150
  .then(() => {
151
151
  this.didDelete(delItem);
@@ -164,7 +164,7 @@ class APIHandler {
164
164
  .addEachTask({
165
165
  data: conflicts || [],
166
166
  generator: (updateItem) => {
167
- const updateFN = this.getClientFN('update');
167
+ const updateFN = this.getClientFN(this.functions.update);
168
168
  const params = { [this.id]: updateItem[this.id] };
169
169
  const payload = (0, utils_1.stripFields)(Object.assign({}, updateItem), this.stripUpdateFields);
170
170
  return updateFN(params, payload)
@@ -180,7 +180,7 @@ class APIHandler {
180
180
  .addEachTask({
181
181
  data: create || [],
182
182
  generator: (createItem) => {
183
- const createFunction = this.getClientFN('create');
183
+ const createFunction = this.getClientFN(this.functions.create);
184
184
  return createFunction(createItem)
185
185
  .then((data) => {
186
186
  this.didCreate(data);
@@ -197,7 +197,7 @@ class APIHandler {
197
197
  .addEachTask({
198
198
  data: update || [],
199
199
  generator: (updateItem) => {
200
- const updateFN = this.getClientFN('update');
200
+ const updateFN = this.getClientFN(this.functions.update);
201
201
  const params = { [this.id]: updateItem[this.id] };
202
202
  const payload = (0, utils_1.stripFields)(Object.assign({}, updateItem), this.stripUpdateFields);
203
203
  return updateFN(params, payload)
@@ -141,7 +141,7 @@ class RulesHandler extends default_1.default {
141
141
  if (rulesSameOrder.length > 0) {
142
142
  const formatted = rulesSameOrder.map((dups) => dups.map((d) => `${d.name}`));
143
143
  throw new validationError_1.default(`There are multiple rules for the following stage-order combinations
144
- ${(0, utils_1.dumpJSON)(formatted)}.
144
+ ${(0, utils_1.convertJsonToString)(formatted)}.
145
145
  Only one rule must be defined for the same order number in a stage.`);
146
146
  }
147
147
  // Detect Rules that are changing stage as it's not allowed.
@@ -154,7 +154,7 @@ class RulesHandler extends default_1.default {
154
154
  .map((r) => r.name);
155
155
  if (stateChanged.length > 0) {
156
156
  throw new validationError_1.default(`The following rules changed stage which is not allowed:
157
- ${(0, utils_1.dumpJSON)(stateChanged)}.
157
+ ${(0, utils_1.convertJsonToString)(stateChanged)}.
158
158
  Rename the rules to recreate them and avoid this error.`);
159
159
  }
160
160
  yield _super.validate.call(this, assets);
@@ -184,7 +184,7 @@ class RulesHandler extends default_1.default {
184
184
  order: rule.order,
185
185
  id: rule.id,
186
186
  };
187
- logger_1.default.info(`Temporally re-order Rule ${(0, utils_1.dumpJSON)(updated)}`);
187
+ logger_1.default.info(`Temporally re-order Rule ${(0, utils_1.convertJsonToString)(updated)}`);
188
188
  }),
189
189
  })
190
190
  .promise();
@@ -76,7 +76,7 @@ class TenantHandler extends default_1.default {
76
76
  return;
77
77
  const pageKeys = Object.keys(tenant).filter((k) => blockPageKeys.includes(k));
78
78
  if (pageKeys.length > 0) {
79
- throw new validationError_1.default(`The following pages ${(0, utils_1.dumpJSON)(pageKeys)} were found in tenant settings. Pages should be set separately. Please refer to the documentation.`);
79
+ throw new validationError_1.default(`The following pages ${(0, utils_1.convertJsonToString)(pageKeys)} were found in tenant settings. Pages should be set separately. Please refer to the documentation.`);
80
80
  }
81
81
  });
82
82
  }
@@ -1,11 +1,34 @@
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 __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.areArraysEquals = exports.filterExcluded = exports.duplicateItems = exports.getEnabledClients = exports.stripFields = exports.dumpJSON = exports.flatten = exports.loadFileAndReplaceKeywords = exports.convertClientNamesToIds = exports.convertClientNameToId = exports.keywordReplace = exports.keywordStringReplace = exports.keywordArrayReplace = void 0;
29
+ exports.areArraysEquals = exports.filterExcluded = exports.duplicateItems = exports.getEnabledClients = exports.stripFields = exports.convertJsonToString = exports.flatten = exports.loadFileAndReplaceKeywords = exports.convertClientNamesToIds = exports.convertClientNameToId = exports.keywordReplace = exports.keywordStringReplace = exports.keywordArrayReplace = void 0;
7
30
  const path_1 = __importDefault(require("path"));
8
- const fs_1 = __importDefault(require("fs"));
31
+ const fs_1 = __importStar(require("fs"));
9
32
  const dot_prop_1 = __importDefault(require("dot-prop"));
10
33
  const lodash_1 = __importDefault(require("lodash"));
11
34
  const logger_1 = __importDefault(require("./logger"));
@@ -23,6 +46,7 @@ exports.keywordArrayReplace = keywordArrayReplace;
23
46
  function keywordStringReplace(input, mappings) {
24
47
  Object.keys(mappings).forEach(function (key) {
25
48
  const regex = new RegExp(`##${key}##`, 'g');
49
+ // @ts-ignore TODO: come back and distinguish strings vs array replacement.
26
50
  input = input.replace(regex, mappings[key]);
27
51
  });
28
52
  return input;
@@ -48,11 +72,12 @@ function convertClientNamesToIds(names, clients) {
48
72
  if (names.includes(client.name)) {
49
73
  const index = resolvedNames.findIndex((item) => item.name === client.name);
50
74
  resolvedNames[index].resolved = true;
51
- acc.push(client.client_id);
75
+ return [...acc, client.client_id];
52
76
  }
53
- return acc;
77
+ return [...acc];
54
78
  }, []);
55
79
  const unresolved = resolvedNames.filter((item) => !item.resolved).map((item) => item.name);
80
+ // @ts-ignore TODO: come back and refactor to use map instead of reduce.
56
81
  return [...unresolved, ...result];
57
82
  }
58
83
  exports.convertClientNamesToIds = convertClientNamesToIds;
@@ -60,7 +85,7 @@ function loadFileAndReplaceKeywords(file, mappings) {
60
85
  // Load file and replace keyword mappings
61
86
  const f = path_1.default.resolve(file);
62
87
  try {
63
- fs_1.default.accessSync(f, fs_1.default.F_OK);
88
+ fs_1.default.accessSync(f, fs_1.constants.F_OK);
64
89
  if (mappings) {
65
90
  return keywordReplace(fs_1.default.readFileSync(f, 'utf8'), mappings);
66
91
  }
@@ -76,10 +101,10 @@ function flatten(list) {
76
101
  return list.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
77
102
  }
78
103
  exports.flatten = flatten;
79
- function dumpJSON(obj, spacing = 0) {
104
+ function convertJsonToString(obj, spacing = 0) {
80
105
  return JSON.stringify(obj, null, spacing);
81
106
  }
82
- exports.dumpJSON = dumpJSON;
107
+ exports.convertJsonToString = convertJsonToString;
83
108
  function stripFields(obj, fields) {
84
109
  // Strip object fields supporting dot notation (ie: a.deep.field)
85
110
  const stripped = [];
package/lib/utils.js CHANGED
@@ -10,18 +10,18 @@ const sanitize_filename_1 = __importDefault(require("sanitize-filename"));
10
10
  const dot_prop_1 = __importDefault(require("dot-prop"));
11
11
  const tools_1 = require("./tools");
12
12
  const logger_1 = __importDefault(require("./logger"));
13
- function isDirectory(f) {
13
+ function isDirectory(filePath) {
14
14
  try {
15
- return fs_extra_1.default.statSync(path_1.default.resolve(f)).isDirectory();
15
+ return fs_extra_1.default.statSync(path_1.default.resolve(filePath)).isDirectory();
16
16
  }
17
17
  catch (err) {
18
18
  return false;
19
19
  }
20
20
  }
21
21
  exports.isDirectory = isDirectory;
22
- function isFile(f) {
22
+ function isFile(filePath) {
23
23
  try {
24
- return fs_extra_1.default.statSync(path_1.default.resolve(f)).isFile();
24
+ return fs_extra_1.default.statSync(path_1.default.resolve(filePath)).isFile();
25
25
  }
26
26
  catch (err) {
27
27
  return false;
@@ -151,7 +151,8 @@ function clearTenantFlags(tenant) {
151
151
  }
152
152
  }
153
153
  exports.clearTenantFlags = clearTenantFlags;
154
- function ensureProp(obj, props, value = '') {
154
+ function ensureProp(obj, props) {
155
+ const value = '';
155
156
  if (!dot_prop_1.default.has(obj, props)) {
156
157
  dot_prop_1.default.set(obj, props, value);
157
158
  }
@@ -159,8 +160,10 @@ function ensureProp(obj, props, value = '') {
159
160
  exports.ensureProp = ensureProp;
160
161
  function clearClientArrays(client) {
161
162
  const propsToClear = ['allowed_clients', 'allowed_logout_urls', 'allowed_origins', 'callbacks'];
163
+ //If designated properties are null, set them as empty arrays instead
162
164
  Object.keys(client).forEach((prop) => {
163
165
  if (propsToClear.indexOf(prop) >= 0 && !client[prop]) {
166
+ //TODO: understand why setting as empty array instead of deleting null prop. Ex: `delete client[prop]`
164
167
  client[prop] = [];
165
168
  }
166
169
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auth0-deploy-cli",
3
- "version": "7.7.0",
3
+ "version": "7.7.1",
4
4
  "description": "A command line tool for deploying updates to your Auth0 tenant",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -44,6 +44,8 @@
44
44
  "nconf": "^0.11.0",
45
45
  "promise-pool-executor": "^1.1.1",
46
46
  "sanitize-filename": "^1.6.1",
47
+ "sinon": "^13.0.1",
48
+ "sinon-chai": "^3.7.0",
47
49
  "winston": "^2.3.0",
48
50
  "yargs": "^15.3.1"
49
51
  },