@pnp/cli-microsoft365 4.3.0-beta.fd397f5 → 5.0.0-beta.117f66f
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/README.md +1 -1
- package/dist/appInsights.js +2 -1
- package/dist/cli/Cli.js +22 -3
- package/dist/m365/aad/commands/oauth2grant/oauth2grant-list.js +7 -7
- package/dist/m365/aad/commands/oauth2grant/oauth2grant-remove.js +36 -12
- package/dist/m365/aad/commands/sp/sp-get.js +44 -21
- package/dist/m365/aad/commands/user/user-password-validate.js +42 -0
- package/dist/m365/aad/commands.js +1 -0
- package/dist/m365/app/commands/permission/permission-list.js +266 -0
- package/dist/m365/app/commands.js +7 -0
- package/dist/m365/base/AppCommand.js +76 -0
- package/dist/m365/pa/commands/app/app-list.js +28 -1
- package/dist/request.js +9 -4
- package/docs/docs/cmd/_global.md +2 -2
- package/docs/docs/cmd/aad/oauth2grant/oauth2grant-list.md +4 -3
- package/docs/docs/cmd/aad/oauth2grant/oauth2grant-remove.md +9 -0
- package/docs/docs/cmd/aad/sp/sp-get.md +2 -1
- package/docs/docs/cmd/aad/user/user-password-validate.md +29 -0
- package/docs/docs/cmd/app/permission/permission-list.md +36 -0
- package/docs/docs/cmd/pa/app/app-list.md +17 -1
- package/docs/docs/cmd/spfx/project/project-externalize.md +1 -1
- package/docs/docs/cmd/spfx/project/project-rename.md +1 -1
- package/docs/docs/cmd/spfx/spfx-doctor.md +1 -1
- package/npm-shrinkwrap.json +603 -743
- package/package.json +18 -15
package/README.md
CHANGED
|
@@ -179,7 +179,7 @@ m365 spo site get --url https://contoso.sharepoint.com --output text
|
|
|
179
179
|
|
|
180
180
|
## Build
|
|
181
181
|
|
|
182
|
-
To build and run this CLI locally, you will need [`node`](https://nodejs.org) `>=
|
|
182
|
+
To build and run this CLI locally, you will need [`node`](https://nodejs.org) `>= 16.0.0` installed.
|
|
183
183
|
|
|
184
184
|
```sh
|
|
185
185
|
# Clone this repository
|
package/dist/appInsights.js
CHANGED
|
@@ -20,7 +20,8 @@ const env = process.env.CLIMICROSOFT365_ENV !== undefined ? process.env.CLIMICRO
|
|
|
20
20
|
appInsights.defaultClient.commonProperties = {
|
|
21
21
|
version: version,
|
|
22
22
|
node: process.version,
|
|
23
|
-
env: env
|
|
23
|
+
env: env,
|
|
24
|
+
ci: Boolean(process.env.CI).toString()
|
|
24
25
|
};
|
|
25
26
|
appInsights.defaultClient.context.tags['ai.session.id'] = crypto.randomBytes(24).toString('base64');
|
|
26
27
|
appInsights.defaultClient.context.tags['ai.cloud.roleInstance'] = crypto.createHash('sha256').update(appInsights.defaultClient.context.tags['ai.cloud.roleInstance']).digest('hex');
|
package/dist/cli/Cli.js
CHANGED
|
@@ -17,6 +17,7 @@ const path = require("path");
|
|
|
17
17
|
const appInsights_1 = require("../appInsights");
|
|
18
18
|
const Command_1 = require("../Command");
|
|
19
19
|
const config_1 = require("../config");
|
|
20
|
+
const request_1 = require("../request");
|
|
20
21
|
const settingsNames_1 = require("../settingsNames");
|
|
21
22
|
const Utils_1 = require("../Utils");
|
|
22
23
|
const packageJSON = require('../../package.json');
|
|
@@ -204,16 +205,20 @@ class Cli {
|
|
|
204
205
|
}
|
|
205
206
|
};
|
|
206
207
|
if (args.options.debug) {
|
|
207
|
-
|
|
208
|
+
logErr.push(`Executing command ${command.name} with options ${JSON.stringify(args)}`);
|
|
208
209
|
}
|
|
209
210
|
// store the current command name, if any and set the name to the name of
|
|
210
211
|
// the command to execute
|
|
211
212
|
const cli = Cli.getInstance();
|
|
212
213
|
const parentCommandName = cli.currentCommandName;
|
|
213
214
|
cli.currentCommandName = command.getCommandName();
|
|
215
|
+
// store the current logger if any
|
|
216
|
+
const currentLogger = request_1.default.logger;
|
|
214
217
|
command.action(logger, args, (err) => {
|
|
215
218
|
// restore the original command name
|
|
216
219
|
cli.currentCommandName = parentCommandName;
|
|
220
|
+
// restore the original logger
|
|
221
|
+
request_1.default.logger = currentLogger;
|
|
217
222
|
if (err) {
|
|
218
223
|
return reject({
|
|
219
224
|
error: err,
|
|
@@ -416,11 +421,11 @@ class Cli {
|
|
|
416
421
|
if (arrayType !== 'object') {
|
|
417
422
|
return logStatement.join(os.EOL);
|
|
418
423
|
}
|
|
419
|
-
// if output type has been set to 'text', process the retrieved
|
|
424
|
+
// if output type has been set to 'text' or 'csv', process the retrieved
|
|
420
425
|
// data so that returned objects contain only default properties specified
|
|
421
426
|
// on the current command. If there is no current command or the
|
|
422
427
|
// command doesn't specify default properties, return original data
|
|
423
|
-
if (options.output === 'text') {
|
|
428
|
+
if (options.output === 'text' || options.output === 'csv') {
|
|
424
429
|
const cli = Cli.getInstance();
|
|
425
430
|
const currentCommand = cli.commandToExecute;
|
|
426
431
|
if (arrayType === 'object' &&
|
|
@@ -440,6 +445,20 @@ class Cli {
|
|
|
440
445
|
}
|
|
441
446
|
}
|
|
442
447
|
}
|
|
448
|
+
if (options.output === 'csv') {
|
|
449
|
+
const { stringify } = require('csv-stringify/sync');
|
|
450
|
+
/*
|
|
451
|
+
https://csv.js.org/stringify/options/
|
|
452
|
+
header: Display the column names on the first line if the columns option is provided or discovered.
|
|
453
|
+
escape: Single character used for escaping; only apply to characters matching the quote and the escape options default to ".
|
|
454
|
+
quote: The quote characters surrounding a field, defaults to the " (double quotation marks), an empty quote value will preserve the original field, whether it contains quotation marks or not.
|
|
455
|
+
quoted: Boolean, default to false, quote all the non-empty fields even if not required.
|
|
456
|
+
quotedEmpty: Quote empty strings and overrides quoted_string on empty strings when defined; default is false.
|
|
457
|
+
*/
|
|
458
|
+
return stringify(logStatement, {
|
|
459
|
+
header: true
|
|
460
|
+
});
|
|
461
|
+
}
|
|
443
462
|
// display object as a list of key-value pairs
|
|
444
463
|
if (logStatement.length === 1) {
|
|
445
464
|
const obj = logStatement[0];
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const request_1 = require("../../../../request");
|
|
4
4
|
const Utils_1 = require("../../../../Utils");
|
|
5
|
-
const
|
|
5
|
+
const GraphCommand_1 = require("../../../base/GraphCommand");
|
|
6
6
|
const commands_1 = require("../../commands");
|
|
7
|
-
class AadOAuth2GrantListCommand extends
|
|
7
|
+
class AadOAuth2GrantListCommand extends GraphCommand_1.default {
|
|
8
8
|
get name() {
|
|
9
9
|
return commands_1.default.OAUTH2GRANT_LIST;
|
|
10
10
|
}
|
|
@@ -19,9 +19,9 @@ class AadOAuth2GrantListCommand extends AadCommand_1.default {
|
|
|
19
19
|
logger.logToStderr(`Retrieving list of OAuth grants for the service principal...`);
|
|
20
20
|
}
|
|
21
21
|
const requestOptions = {
|
|
22
|
-
url: `${this.resource}/
|
|
22
|
+
url: `${this.resource}/v1.0/oauth2PermissionGrants?$filter=clientId eq '${encodeURIComponent(args.options.spObjectId)}'`,
|
|
23
23
|
headers: {
|
|
24
|
-
accept: 'application/json;odata=
|
|
24
|
+
accept: 'application/json;odata.metadata=none'
|
|
25
25
|
},
|
|
26
26
|
responseType: 'json'
|
|
27
27
|
};
|
|
@@ -37,15 +37,15 @@ class AadOAuth2GrantListCommand extends AadCommand_1.default {
|
|
|
37
37
|
options() {
|
|
38
38
|
const options = [
|
|
39
39
|
{
|
|
40
|
-
option: '-i, --
|
|
40
|
+
option: '-i, --spObjectId <spObjectId>'
|
|
41
41
|
}
|
|
42
42
|
];
|
|
43
43
|
const parentOptions = super.options();
|
|
44
44
|
return options.concat(parentOptions);
|
|
45
45
|
}
|
|
46
46
|
validate(args) {
|
|
47
|
-
if (!Utils_1.default.isValidGuid(args.options.
|
|
48
|
-
return `${args.options.
|
|
47
|
+
if (!Utils_1.default.isValidGuid(args.options.spObjectId)) {
|
|
48
|
+
return `${args.options.spObjectId} is not a valid GUID`;
|
|
49
49
|
}
|
|
50
50
|
return true;
|
|
51
51
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const cli_1 = require("../../../../cli");
|
|
3
4
|
const request_1 = require("../../../../request");
|
|
4
5
|
const GraphCommand_1 = require("../../../base/GraphCommand");
|
|
5
6
|
const commands_1 = require("../../commands");
|
|
@@ -11,24 +12,47 @@ class AadOAuth2GrantRemoveCommand extends GraphCommand_1.default {
|
|
|
11
12
|
return 'Remove specified service principal OAuth2 permissions';
|
|
12
13
|
}
|
|
13
14
|
commandAction(logger, args, cb) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
const removeOauth2Grant = () => {
|
|
16
|
+
if (this.verbose) {
|
|
17
|
+
logger.logToStderr(`Removing OAuth2 permissions...`);
|
|
18
|
+
}
|
|
19
|
+
const requestOptions = {
|
|
20
|
+
url: `${this.resource}/v1.0/oauth2PermissionGrants/${encodeURIComponent(args.options.grantId)}`,
|
|
21
|
+
headers: {
|
|
22
|
+
'accept': 'application/json;odata.metadata=none'
|
|
23
|
+
},
|
|
24
|
+
responseType: 'json'
|
|
25
|
+
};
|
|
26
|
+
request_1.default
|
|
27
|
+
.delete(requestOptions)
|
|
28
|
+
.then(_ => cb(), (rawRes) => this.handleRejectedODataJsonPromise(rawRes, logger, cb));
|
|
23
29
|
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
if (args.options.confirm) {
|
|
31
|
+
removeOauth2Grant();
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
cli_1.Cli.prompt({
|
|
35
|
+
type: 'confirm',
|
|
36
|
+
name: 'continue',
|
|
37
|
+
default: false,
|
|
38
|
+
message: `Are you sure you want to remove the OAuth2 permissions for ${args.options.grantId}?`
|
|
39
|
+
}, (result) => {
|
|
40
|
+
if (!result.continue) {
|
|
41
|
+
cb();
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
removeOauth2Grant();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
27
48
|
}
|
|
28
49
|
options() {
|
|
29
50
|
const options = [
|
|
30
51
|
{
|
|
31
52
|
option: '-i, --grantId <grantId>'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
option: '--confirm'
|
|
32
56
|
}
|
|
33
57
|
];
|
|
34
58
|
const parentOptions = super.options();
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const request_1 = require("../../../../request");
|
|
4
4
|
const Utils_1 = require("../../../../Utils");
|
|
5
|
-
const
|
|
5
|
+
const GraphCommand_1 = require("../../../base/GraphCommand");
|
|
6
6
|
const commands_1 = require("../../commands");
|
|
7
|
-
class AadSpGetCommand extends
|
|
7
|
+
class AadSpGetCommand extends GraphCommand_1.default {
|
|
8
8
|
get name() {
|
|
9
9
|
return commands_1.default.SP_GET;
|
|
10
10
|
}
|
|
@@ -18,35 +18,58 @@ class AadSpGetCommand extends AadCommand_1.default {
|
|
|
18
18
|
telemetryProps.objectId = (!(!args.options.objectId)).toString();
|
|
19
19
|
return telemetryProps;
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
21
|
+
getSpId(args) {
|
|
22
|
+
if (args.options.objectId) {
|
|
23
|
+
return Promise.resolve(args.options.objectId);
|
|
24
24
|
}
|
|
25
25
|
let spMatchQuery = '';
|
|
26
|
-
if (args.options.
|
|
27
|
-
spMatchQuery = `appId eq '${encodeURIComponent(args.options.appId)}'`;
|
|
28
|
-
}
|
|
29
|
-
else if (args.options.objectId) {
|
|
30
|
-
spMatchQuery = `objectId eq '${encodeURIComponent(args.options.objectId)}'`;
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
26
|
+
if (args.options.displayName) {
|
|
33
27
|
spMatchQuery = `displayName eq '${encodeURIComponent(args.options.displayName)}'`;
|
|
34
28
|
}
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
else if (args.options.appId) {
|
|
30
|
+
spMatchQuery = `appId eq '${encodeURIComponent(args.options.appId)}'`;
|
|
31
|
+
}
|
|
32
|
+
const idRequestOptions = {
|
|
33
|
+
url: `${this.resource}/v1.0/servicePrincipals?$filter=${spMatchQuery}`,
|
|
37
34
|
headers: {
|
|
38
|
-
accept: 'application/json;odata=
|
|
35
|
+
accept: 'application/json;odata.metadata=none'
|
|
39
36
|
},
|
|
40
37
|
responseType: 'json'
|
|
41
38
|
};
|
|
42
|
-
request_1.default
|
|
43
|
-
.get(
|
|
44
|
-
.then(
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
return request_1.default
|
|
40
|
+
.get(idRequestOptions)
|
|
41
|
+
.then(response => {
|
|
42
|
+
const spItem = response.value[0];
|
|
43
|
+
if (!spItem) {
|
|
44
|
+
return Promise.reject(`The specified Azure AD app does not exist`);
|
|
45
|
+
}
|
|
46
|
+
if (response.value.length > 1) {
|
|
47
|
+
return Promise.reject(`Multiple Azure AD apps with name ${args.options.displayName} found: ${response.value.map(x => x.id)}`);
|
|
47
48
|
}
|
|
49
|
+
return Promise.resolve(spItem.id);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
commandAction(logger, args, cb) {
|
|
53
|
+
if (this.verbose) {
|
|
54
|
+
logger.logToStderr(`Retrieving service principal information...`);
|
|
55
|
+
}
|
|
56
|
+
this
|
|
57
|
+
.getSpId(args)
|
|
58
|
+
.then((id) => {
|
|
59
|
+
const requestOptions = {
|
|
60
|
+
url: `${this.resource}/v1.0/servicePrincipals/${id}`,
|
|
61
|
+
headers: {
|
|
62
|
+
accept: 'application/json;odata.metadata=none',
|
|
63
|
+
'content-type': 'application/json;odata.metadata=none'
|
|
64
|
+
},
|
|
65
|
+
responseType: 'json'
|
|
66
|
+
};
|
|
67
|
+
return request_1.default.get(requestOptions);
|
|
68
|
+
})
|
|
69
|
+
.then((res) => {
|
|
70
|
+
logger.log(res);
|
|
48
71
|
cb();
|
|
49
|
-
}, (
|
|
72
|
+
}, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
|
|
50
73
|
}
|
|
51
74
|
options() {
|
|
52
75
|
const options = [
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const request_1 = require("../../../../request");
|
|
4
|
+
const GraphCommand_1 = require("../../../base/GraphCommand");
|
|
5
|
+
const commands_1 = require("../../commands");
|
|
6
|
+
class AadUserPasswordValidateCommand extends GraphCommand_1.default {
|
|
7
|
+
get name() {
|
|
8
|
+
return commands_1.default.USER_PASSWORD_VALIDATE;
|
|
9
|
+
}
|
|
10
|
+
get description() {
|
|
11
|
+
return "Check a user's password against the organization's password validation policy";
|
|
12
|
+
}
|
|
13
|
+
commandAction(logger, args, cb) {
|
|
14
|
+
const requestOptions = {
|
|
15
|
+
url: `${this.resource}/beta/users/validatePassword`,
|
|
16
|
+
headers: {
|
|
17
|
+
accept: 'application/json;odata.metadata=none'
|
|
18
|
+
},
|
|
19
|
+
data: {
|
|
20
|
+
password: args.options.password
|
|
21
|
+
},
|
|
22
|
+
responseType: 'json'
|
|
23
|
+
};
|
|
24
|
+
request_1.default
|
|
25
|
+
.post(requestOptions)
|
|
26
|
+
.then((res) => {
|
|
27
|
+
logger.log(res);
|
|
28
|
+
cb();
|
|
29
|
+
}, (err) => this.handleRejectedODataJsonPromise(err, logger, cb));
|
|
30
|
+
}
|
|
31
|
+
options() {
|
|
32
|
+
const options = [
|
|
33
|
+
{
|
|
34
|
+
option: '-p, --password <password>'
|
|
35
|
+
}
|
|
36
|
+
];
|
|
37
|
+
const parentOptions = super.options();
|
|
38
|
+
return options.concat(parentOptions);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
module.exports = new AadUserPasswordValidateCommand();
|
|
42
|
+
//# sourceMappingURL=user-password-validate.js.map
|
|
@@ -51,6 +51,7 @@ exports.default = {
|
|
|
51
51
|
SP_GET: `${prefix} sp get`,
|
|
52
52
|
USER_GET: `${prefix} user get`,
|
|
53
53
|
USER_LIST: `${prefix} user list`,
|
|
54
|
+
USER_PASSWORD_VALIDATE: `${prefix} user password validate`,
|
|
54
55
|
USER_SET: `${prefix} user set`
|
|
55
56
|
};
|
|
56
57
|
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const cli_1 = require("../../../../cli");
|
|
13
|
+
const request_1 = require("../../../../request");
|
|
14
|
+
const appGetCommand = require("../../../aad/commands/app/app-get");
|
|
15
|
+
const AppCommand_1 = require("../../../base/AppCommand");
|
|
16
|
+
const commands_1 = require("../../commands");
|
|
17
|
+
var GetServicePrincipal;
|
|
18
|
+
(function (GetServicePrincipal) {
|
|
19
|
+
GetServicePrincipal[GetServicePrincipal["withPermissions"] = 0] = "withPermissions";
|
|
20
|
+
GetServicePrincipal[GetServicePrincipal["withPermissionDefinitions"] = 1] = "withPermissionDefinitions";
|
|
21
|
+
})(GetServicePrincipal || (GetServicePrincipal = {}));
|
|
22
|
+
class AppPermissionListCommand extends AppCommand_1.default {
|
|
23
|
+
get name() {
|
|
24
|
+
return commands_1.default.PERMISSION_LIST;
|
|
25
|
+
}
|
|
26
|
+
get description() {
|
|
27
|
+
return 'Lists API permissions for the current AAD app';
|
|
28
|
+
}
|
|
29
|
+
commandAction(logger, args, cb) {
|
|
30
|
+
this
|
|
31
|
+
.getServicePrincipal({ appId: this.appId }, logger, GetServicePrincipal.withPermissions)
|
|
32
|
+
.then(servicePrincipal => {
|
|
33
|
+
if (servicePrincipal) {
|
|
34
|
+
// service principal found, get permissions from the service principal
|
|
35
|
+
return this.getServicePrincipalPermissions(servicePrincipal, logger);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// service principal not found, get permissions from app registration
|
|
39
|
+
return this.getAppRegPermissions(this.appId, logger);
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
.then(permissions => {
|
|
43
|
+
logger.log(permissions);
|
|
44
|
+
cb();
|
|
45
|
+
}, err => this.handleRejectedODataJsonPromise(err, logger, cb));
|
|
46
|
+
}
|
|
47
|
+
getServicePrincipal(servicePrincipalInfo, logger, mode) {
|
|
48
|
+
var _a;
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
if (this.verbose) {
|
|
51
|
+
logger.logToStderr(`Retrieving service principal ${(_a = servicePrincipalInfo.appId) !== null && _a !== void 0 ? _a : servicePrincipalInfo.id}`);
|
|
52
|
+
}
|
|
53
|
+
const lookupUrl = servicePrincipalInfo.appId ? `?$filter=appId eq '${servicePrincipalInfo.appId}'&` : `/${servicePrincipalInfo.id}?`;
|
|
54
|
+
const requestOptions = {
|
|
55
|
+
url: `${this.resource}/v1.0/servicePrincipals${lookupUrl}$select=appId,id,displayName`,
|
|
56
|
+
headers: {
|
|
57
|
+
accept: 'application/json;odata.metadata=none'
|
|
58
|
+
},
|
|
59
|
+
responseType: 'json'
|
|
60
|
+
};
|
|
61
|
+
const response = yield request_1.default.get(requestOptions);
|
|
62
|
+
if ((servicePrincipalInfo.id && !response) ||
|
|
63
|
+
(servicePrincipalInfo.appId && response.value.length === 0)) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const servicePrincipal = servicePrincipalInfo.appId ?
|
|
67
|
+
response.value[0] :
|
|
68
|
+
response;
|
|
69
|
+
if (this.verbose) {
|
|
70
|
+
logger.logToStderr(`Retrieving permissions for service principal ${servicePrincipal.id}...`);
|
|
71
|
+
}
|
|
72
|
+
const permissionsPromises = [];
|
|
73
|
+
switch (mode) {
|
|
74
|
+
case GetServicePrincipal.withPermissions:
|
|
75
|
+
const appRoleAssignmentsRequestOptions = {
|
|
76
|
+
url: `${this.resource}/v1.0/servicePrincipals/${servicePrincipal.id}/appRoleAssignments`,
|
|
77
|
+
headers: {
|
|
78
|
+
accept: 'application/json;odata.metadata=none'
|
|
79
|
+
},
|
|
80
|
+
responseType: 'json'
|
|
81
|
+
};
|
|
82
|
+
const oauth2PermissionGrantsRequestOptions = {
|
|
83
|
+
url: `${this.resource}/v1.0/servicePrincipals/${servicePrincipal.id}/oauth2PermissionGrants`,
|
|
84
|
+
headers: {
|
|
85
|
+
accept: 'application/json;odata.metadata=none'
|
|
86
|
+
},
|
|
87
|
+
responseType: 'json'
|
|
88
|
+
};
|
|
89
|
+
permissionsPromises.push(...[
|
|
90
|
+
request_1.default.get(appRoleAssignmentsRequestOptions),
|
|
91
|
+
request_1.default.get(oauth2PermissionGrantsRequestOptions)
|
|
92
|
+
]);
|
|
93
|
+
break;
|
|
94
|
+
case GetServicePrincipal.withPermissionDefinitions:
|
|
95
|
+
const oauth2PermissionScopesRequestOptions = {
|
|
96
|
+
url: `${this.resource}/v1.0/servicePrincipals/${servicePrincipal.id}/oauth2PermissionScopes`,
|
|
97
|
+
headers: {
|
|
98
|
+
accept: 'application/json;odata.metadata=none'
|
|
99
|
+
},
|
|
100
|
+
responseType: 'json'
|
|
101
|
+
};
|
|
102
|
+
const appRolesRequestOptions = {
|
|
103
|
+
url: `${this.resource}/v1.0/servicePrincipals/${servicePrincipal.id}/appRoles`,
|
|
104
|
+
headers: {
|
|
105
|
+
accept: 'application/json;odata.metadata=none'
|
|
106
|
+
},
|
|
107
|
+
responseType: 'json'
|
|
108
|
+
};
|
|
109
|
+
permissionsPromises.push(...[
|
|
110
|
+
request_1.default.get(oauth2PermissionScopesRequestOptions),
|
|
111
|
+
request_1.default.get(appRolesRequestOptions)
|
|
112
|
+
]);
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
const permissions = yield Promise.all(permissionsPromises);
|
|
116
|
+
switch (mode) {
|
|
117
|
+
case GetServicePrincipal.withPermissions:
|
|
118
|
+
servicePrincipal.appRoleAssignments = permissions[0].value;
|
|
119
|
+
servicePrincipal.oauth2PermissionGrants = permissions[1].value;
|
|
120
|
+
break;
|
|
121
|
+
case GetServicePrincipal.withPermissionDefinitions:
|
|
122
|
+
servicePrincipal.oauth2PermissionScopes = permissions[0].value;
|
|
123
|
+
servicePrincipal.appRoles = permissions[1].value;
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
return servicePrincipal;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
getServicePrincipalPermissions(servicePrincipal, logger) {
|
|
130
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
131
|
+
if (this.verbose) {
|
|
132
|
+
logger.logToStderr(`Resolving permissions for the service principal...`);
|
|
133
|
+
}
|
|
134
|
+
const apiPermissions = [];
|
|
135
|
+
// hash table for resolving resource IDs to names
|
|
136
|
+
const resourceLookup = {};
|
|
137
|
+
// list of service principals for which to load permissions
|
|
138
|
+
const servicePrincipalsToResolve = [];
|
|
139
|
+
const appRoleAssignments = servicePrincipal.appRoleAssignments;
|
|
140
|
+
apiPermissions.push(...appRoleAssignments.map(appRoleAssignment => {
|
|
141
|
+
// store resource name for resolving OAuth2 grants
|
|
142
|
+
resourceLookup[appRoleAssignment.resourceId] = appRoleAssignment.resourceDisplayName;
|
|
143
|
+
// add to the list of service principals to load to get the app role
|
|
144
|
+
// display name
|
|
145
|
+
if (!servicePrincipalsToResolve.find(r => r.id === appRoleAssignment.resourceId)) {
|
|
146
|
+
servicePrincipalsToResolve.push({ id: appRoleAssignment.resourceId });
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
resource: appRoleAssignment.resourceDisplayName,
|
|
150
|
+
// we store the app role ID temporarily and will later resolve to display name
|
|
151
|
+
permission: appRoleAssignment.appRoleId,
|
|
152
|
+
type: 'Application'
|
|
153
|
+
};
|
|
154
|
+
}));
|
|
155
|
+
const oauth2Grants = servicePrincipal.oauth2PermissionGrants;
|
|
156
|
+
oauth2Grants.forEach(oauth2Grant => {
|
|
157
|
+
var _a;
|
|
158
|
+
// see if we can resolve the resource name from the resources
|
|
159
|
+
// retrieved from app role assignments
|
|
160
|
+
const resource = (_a = resourceLookup[oauth2Grant.resourceId]) !== null && _a !== void 0 ? _a : oauth2Grant.resourceId;
|
|
161
|
+
if (resource === oauth2Grant.resourceId &&
|
|
162
|
+
!servicePrincipalsToResolve.find(r => r.id === oauth2Grant.resourceId)) {
|
|
163
|
+
// resource name not found in the resources
|
|
164
|
+
// add it to the list of resources to resolve
|
|
165
|
+
servicePrincipalsToResolve.push({ id: oauth2Grant.resourceId });
|
|
166
|
+
}
|
|
167
|
+
const scopes = oauth2Grant.scope.split(' ');
|
|
168
|
+
scopes.forEach(scope => {
|
|
169
|
+
apiPermissions.push({
|
|
170
|
+
resource,
|
|
171
|
+
permission: scope,
|
|
172
|
+
type: 'Delegated'
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
if (servicePrincipalsToResolve.length > 0) {
|
|
177
|
+
const servicePrincipals = yield Promise
|
|
178
|
+
.all(servicePrincipalsToResolve
|
|
179
|
+
.map(servicePrincipalInfo => this.getServicePrincipal(servicePrincipalInfo, logger, GetServicePrincipal.withPermissionDefinitions)));
|
|
180
|
+
servicePrincipals.forEach(servicePrincipal => {
|
|
181
|
+
apiPermissions.forEach(apiPermission => {
|
|
182
|
+
var _a, _b;
|
|
183
|
+
if (apiPermission.resource === servicePrincipal.id) {
|
|
184
|
+
apiPermission.resource = servicePrincipal.displayName;
|
|
185
|
+
}
|
|
186
|
+
if (apiPermission.resource === servicePrincipal.displayName &&
|
|
187
|
+
apiPermission.type === 'Application') {
|
|
188
|
+
apiPermission.permission = (_b = (_a = servicePrincipal.appRoles
|
|
189
|
+
.find(appRole => appRole.id === apiPermission.permission)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : apiPermission.permission;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return apiPermissions;
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
getAppRegistration(appId, logger) {
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
if (this.verbose) {
|
|
200
|
+
logger.logToStderr(`Retrieving Azure AD application registration ${appId}`);
|
|
201
|
+
}
|
|
202
|
+
const options = {
|
|
203
|
+
appId: appId,
|
|
204
|
+
output: 'json',
|
|
205
|
+
debug: this.debug,
|
|
206
|
+
verbose: this.verbose
|
|
207
|
+
};
|
|
208
|
+
const output = yield cli_1.Cli.executeCommandWithOutput(appGetCommand, { options: Object.assign(Object.assign({}, options), { _: [] }) });
|
|
209
|
+
if (this.debug) {
|
|
210
|
+
logger.logToStderr(output.stderr);
|
|
211
|
+
}
|
|
212
|
+
return JSON.parse(output.stdout);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
getAppRegPermissions(appId, logger) {
|
|
216
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
217
|
+
const application = yield this.getAppRegistration(appId, logger);
|
|
218
|
+
if (application.requiredResourceAccess.length === 0) {
|
|
219
|
+
return [];
|
|
220
|
+
}
|
|
221
|
+
const servicePrincipalsToResolve = application.requiredResourceAccess
|
|
222
|
+
.map(resourceAccess => {
|
|
223
|
+
return {
|
|
224
|
+
appId: resourceAccess.resourceAppId
|
|
225
|
+
};
|
|
226
|
+
});
|
|
227
|
+
const servicePrincipals = yield Promise
|
|
228
|
+
.all(servicePrincipalsToResolve.map(servicePrincipalInfo => this.getServicePrincipal(servicePrincipalInfo, logger, GetServicePrincipal.withPermissionDefinitions)));
|
|
229
|
+
const apiPermissions = [];
|
|
230
|
+
application.requiredResourceAccess.forEach(requiredResourceAccess => {
|
|
231
|
+
var _a;
|
|
232
|
+
const servicePrincipal = servicePrincipals
|
|
233
|
+
.find(servicePrincipal => (servicePrincipal === null || servicePrincipal === void 0 ? void 0 : servicePrincipal.appId) === requiredResourceAccess.resourceAppId);
|
|
234
|
+
const resourceName = (_a = servicePrincipal === null || servicePrincipal === void 0 ? void 0 : servicePrincipal.displayName) !== null && _a !== void 0 ? _a : requiredResourceAccess.resourceAppId;
|
|
235
|
+
requiredResourceAccess.resourceAccess.forEach(permission => {
|
|
236
|
+
apiPermissions.push({
|
|
237
|
+
resource: resourceName,
|
|
238
|
+
permission: this.getPermissionName(permission.id, permission.type, servicePrincipal),
|
|
239
|
+
type: permission.type === 'Role' ? 'Application' : 'Delegated'
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
return apiPermissions;
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
getPermissionName(permissionId, permissionType, servicePrincipal) {
|
|
247
|
+
var _a, _b, _c, _d;
|
|
248
|
+
if (!servicePrincipal) {
|
|
249
|
+
return permissionId;
|
|
250
|
+
}
|
|
251
|
+
switch (permissionType) {
|
|
252
|
+
case 'Role':
|
|
253
|
+
return (_b = (_a = servicePrincipal.appRoles
|
|
254
|
+
.find(appRole => appRole.id === permissionId)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : permissionId;
|
|
255
|
+
case 'Scope':
|
|
256
|
+
return (_d = (_c = servicePrincipal.oauth2PermissionScopes
|
|
257
|
+
.find(permissionScope => permissionScope.id === permissionId)) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : permissionId;
|
|
258
|
+
}
|
|
259
|
+
/* c8 ignore next 4 */
|
|
260
|
+
// permissionType is either 'Scope' or 'Role' but we need a safe default
|
|
261
|
+
// to avoid building errors. This code will never be reached.
|
|
262
|
+
return permissionId;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
module.exports = new AppPermissionListCommand();
|
|
266
|
+
//# sourceMappingURL=permission-list.js.map
|