@pnp/cli-microsoft365 10.8.0-beta.708bf27 → 10.8.0-beta.cdb5c81
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/.eslintrc.cjs +2 -1
- package/allCommands.json +1 -1
- package/allCommandsFull.json +1 -1
- package/dist/Auth.js +82 -22
- package/dist/cli/cli.js +1 -1
- package/dist/config.js +1 -0
- package/dist/m365/adaptivecard/commands/adaptivecard-send.js +54 -67
- package/dist/m365/cli/commands/app/app-reconsent.js +103 -0
- package/dist/m365/cli/commands.js +1 -0
- package/dist/m365/commands/login.js +1 -1
- package/dist/m365/commands/setup.js +1 -2
- package/dist/m365/entra/commands/organization/organization-list.js +51 -0
- package/dist/m365/entra/commands.js +1 -0
- package/dist/m365/graph/commands/openextension/openextension-set.js +107 -0
- package/dist/m365/graph/commands.js +1 -0
- package/dist/m365/spe/commands/container/container-add.js +85 -0
- package/dist/m365/spe/commands/container/container-list.js +2 -9
- package/dist/m365/spe/commands/container/container-permission-list.js +52 -0
- package/dist/m365/spe/commands/container/container-recyclebinitem-list.js +62 -0
- package/dist/m365/spe/commands/container/container-remove.js +99 -0
- package/dist/m365/spe/commands/containertype/containertype-add.js +11 -11
- package/dist/m365/spe/commands/containertype/containertype-get.js +28 -32
- package/dist/m365/spe/commands/containertype/containertype-list.js +14 -4
- package/dist/m365/spe/commands/containertype/containertype-remove.js +81 -0
- package/dist/m365/spe/commands.js +6 -1
- package/dist/m365/spo/commands/page/page-section-add.js +20 -23
- package/dist/utils/entraServicePrincipal.js +11 -0
- package/dist/utils/formatting.js +12 -0
- package/dist/utils/spe.js +77 -0
- package/dist/utils/spo.js +0 -18
- package/dist/utils/zod.js +26 -1
- package/docs/docs/cmd/adaptivecard/adaptivecard-send.mdx +1 -1
- package/docs/docs/cmd/cli/app/app-reconsent.mdx +63 -0
- package/docs/docs/cmd/entra/organization/organization-list.mdx +154 -0
- package/docs/docs/cmd/graph/openextension/openextension-set.mdx +97 -0
- package/docs/docs/cmd/spe/container/container-activate.mdx +0 -2
- package/docs/docs/cmd/spe/container/container-add.mdx +128 -0
- package/docs/docs/cmd/spe/container/container-permission-list.mdx +90 -0
- package/docs/docs/cmd/spe/container/container-recyclebinitem-list.mdx +96 -0
- package/docs/docs/cmd/spe/container/container-remove.mdx +65 -0
- package/docs/docs/cmd/spe/containertype/containertype-add.mdx +9 -1
- package/docs/docs/cmd/spe/containertype/containertype-get.mdx +8 -0
- package/docs/docs/cmd/spe/containertype/containertype-list.mdx +8 -0
- package/docs/docs/cmd/spe/containertype/containertype-remove.mdx +52 -0
- package/docs/docs/cmd/spo/field/field-get.mdx +0 -1
- package/npm-shrinkwrap.json +894 -477
- package/package.json +10 -10
- package/dist/m365/spe/ContainerProperties.js +0 -2
package/dist/Auth.js
CHANGED
|
@@ -562,19 +562,93 @@ export class Auth {
|
|
|
562
562
|
if (debug) {
|
|
563
563
|
await logger.logToStderr('Trying to retrieve access token using federated identity...');
|
|
564
564
|
}
|
|
565
|
-
if (
|
|
566
|
-
|
|
565
|
+
if (process.env.ACTIONS_ID_TOKEN_REQUEST_URL && process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN) {
|
|
566
|
+
if (debug) {
|
|
567
|
+
await logger.logToStderr('ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN env variables found. The context is GitHub Actions...');
|
|
568
|
+
}
|
|
569
|
+
const federationToken = await this.getFederationTokenFromGithub(logger, debug);
|
|
570
|
+
return this.getAccessTokenWithFederatedToken(resource, federationToken, logger, debug);
|
|
571
|
+
}
|
|
572
|
+
else if (process.env.SYSTEM_OIDCREQUESTURI) {
|
|
573
|
+
if (debug) {
|
|
574
|
+
await logger.logToStderr('SYSTEM_OIDCREQUESTURI env variable found. The context is Azure DevOps...');
|
|
575
|
+
}
|
|
576
|
+
if (!process.env.SYSTEM_ACCESSTOKEN) {
|
|
577
|
+
throw new CommandError(`The SYSTEM_ACCESSTOKEN environment variable is not available. Please check the Azure DevOps pipeline task configuration. It should contain 'SYSTEM_ACCESSTOKEN: $(System.AccessToken)' in the env section.`);
|
|
578
|
+
}
|
|
579
|
+
const serviceConnectionId = process.env.AZURESUBSCRIPTION_SERVICE_CONNECTION_ID;
|
|
580
|
+
const serviceConnectionAppId = process.env.AZURESUBSCRIPTION_CLIENT_ID;
|
|
581
|
+
const serviceConnectionTenantId = process.env.AZURESUBSCRIPTION_TENANT_ID;
|
|
582
|
+
const useServiceConnection = serviceConnectionId && serviceConnectionAppId && serviceConnectionTenantId;
|
|
583
|
+
if (!useServiceConnection) {
|
|
584
|
+
if (debug) {
|
|
585
|
+
await logger.logToStderr('Not using a service connection. Run this command in an AzurePowerShell task to be able to use a service connection.');
|
|
586
|
+
}
|
|
587
|
+
if (!this.connection.appId || this.connection.tenant === 'common') {
|
|
588
|
+
throw new CommandError('The appId and tenant parameters are required when not using a service connection.');
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
else {
|
|
592
|
+
if (debug) {
|
|
593
|
+
if (this.connection.appId || this.connection.tenant !== 'common') {
|
|
594
|
+
await logger.logToStderr('When using a service connection, the appId and tenant values are updated to the values of the service connection.');
|
|
595
|
+
}
|
|
596
|
+
await logger.logToStderr(`Using service connection '${serviceConnectionId}' with app Id '${serviceConnectionAppId}' and tenant Id '${serviceConnectionTenantId}'...`);
|
|
597
|
+
}
|
|
598
|
+
this.connection.appId = serviceConnectionAppId;
|
|
599
|
+
this.connection.tenant = serviceConnectionTenantId;
|
|
600
|
+
}
|
|
601
|
+
const federationToken = await this.getFederationTokenFromAzureDevOps(logger, debug, serviceConnectionId);
|
|
602
|
+
return this.getAccessTokenWithFederatedToken(resource, federationToken, logger, debug);
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
throw new CommandError('Federated identity is currently only supported in GitHub Actions and Azure DevOps.');
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
async getFederationTokenFromGithub(logger, debug) {
|
|
609
|
+
if (debug) {
|
|
610
|
+
await logger.logToStderr('Retrieving GitHub federation token...');
|
|
611
|
+
}
|
|
612
|
+
const requestOptions = {
|
|
613
|
+
url: `${process.env.ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${encodeURIComponent('api://AzureADTokenExchange')}`,
|
|
614
|
+
headers: {
|
|
615
|
+
Authorization: `Bearer ${process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN}`,
|
|
616
|
+
Accept: 'application/json',
|
|
617
|
+
'x-anonymous': true
|
|
618
|
+
},
|
|
619
|
+
responseType: 'json'
|
|
620
|
+
};
|
|
621
|
+
const accessTokenResponse = await request.get(requestOptions);
|
|
622
|
+
return accessTokenResponse.value;
|
|
623
|
+
}
|
|
624
|
+
async getFederationTokenFromAzureDevOps(logger, debug, serviceConnectionId) {
|
|
625
|
+
if (debug) {
|
|
626
|
+
await logger.logToStderr('Retrieving Azure DevOps federation token...');
|
|
567
627
|
}
|
|
628
|
+
const urlSuffix = serviceConnectionId ? `&serviceConnectionId=${serviceConnectionId}` : '';
|
|
629
|
+
const requestOptions = {
|
|
630
|
+
url: `${process.env.SYSTEM_OIDCREQUESTURI}?api-version=7.1${urlSuffix}`,
|
|
631
|
+
headers: {
|
|
632
|
+
Authorization: `Bearer ${process.env.SYSTEM_ACCESSTOKEN}`,
|
|
633
|
+
Accept: 'application/json',
|
|
634
|
+
'Content-Type': 'application/json',
|
|
635
|
+
'x-anonymous': true
|
|
636
|
+
},
|
|
637
|
+
responseType: 'json'
|
|
638
|
+
};
|
|
639
|
+
const accessTokenResponse = await request.post(requestOptions);
|
|
640
|
+
return accessTokenResponse.oidcToken;
|
|
641
|
+
}
|
|
642
|
+
async getAccessTokenWithFederatedToken(resource, federatedToken, logger, debug) {
|
|
568
643
|
if (debug) {
|
|
569
|
-
await logger.logToStderr('
|
|
644
|
+
await logger.logToStderr('Retrieving Entra ID Access Token with federated token...');
|
|
570
645
|
}
|
|
571
|
-
const federationToken = await this.getFederationTokenFromGithub(logger, debug);
|
|
572
646
|
const queryParams = [
|
|
573
647
|
'grant_type=client_credentials',
|
|
574
648
|
`scope=${encodeURIComponent(`${resource}/.default`)}`,
|
|
575
649
|
`client_id=${this.connection.appId}`,
|
|
576
650
|
`client_assertion_type=${encodeURIComponent('urn:ietf:params:oauth:client-assertion-type:jwt-bearer')}`,
|
|
577
|
-
`client_assertion=${
|
|
651
|
+
`client_assertion=${federatedToken}`
|
|
578
652
|
];
|
|
579
653
|
const requestOptions = {
|
|
580
654
|
url: `https://login.microsoftonline.com/${this.connection.tenant}/oauth2/v2.0/token`,
|
|
@@ -587,27 +661,13 @@ export class Auth {
|
|
|
587
661
|
responseType: 'json'
|
|
588
662
|
};
|
|
589
663
|
const accessTokenResponse = await request.post(requestOptions);
|
|
664
|
+
const expiresIn = parseInt(accessTokenResponse.expires_in) * 1000;
|
|
665
|
+
const now = new Date();
|
|
590
666
|
return {
|
|
591
667
|
accessToken: accessTokenResponse.access_token,
|
|
592
|
-
expiresOn: new Date(
|
|
668
|
+
expiresOn: new Date(now.getTime() + expiresIn)
|
|
593
669
|
};
|
|
594
670
|
}
|
|
595
|
-
async getFederationTokenFromGithub(logger, debug) {
|
|
596
|
-
if (debug) {
|
|
597
|
-
await logger.logToStderr('Retrieving GitHub federation token...');
|
|
598
|
-
}
|
|
599
|
-
const requestOptions = {
|
|
600
|
-
url: `${process.env.ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${encodeURIComponent('api://AzureADTokenExchange')}`,
|
|
601
|
-
headers: {
|
|
602
|
-
Authorization: `Bearer ${process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN}`,
|
|
603
|
-
accept: 'application/json',
|
|
604
|
-
'x-anonymous': true
|
|
605
|
-
},
|
|
606
|
-
responseType: 'json'
|
|
607
|
-
};
|
|
608
|
-
const accessTokenResponse = await request.get(requestOptions);
|
|
609
|
-
return accessTokenResponse.value;
|
|
610
|
-
}
|
|
611
671
|
async ensureAccessTokenWithSecret(resource, logger, debug, fetchNew) {
|
|
612
672
|
this.clientApplication = await this.getConfidentialClient(logger, debug, undefined, undefined, this.connection.secret);
|
|
613
673
|
return this.clientApplication.acquireTokenByClientCredential({
|
package/dist/cli/cli.js
CHANGED
|
@@ -406,7 +406,7 @@ async function loadCommandFromFile(commandFileUrl) {
|
|
|
406
406
|
catch { }
|
|
407
407
|
}
|
|
408
408
|
function getCommandInfo(command, filePath = '', helpFilePath = '') {
|
|
409
|
-
const options = command.schema ? zod.
|
|
409
|
+
const options = command.schema ? zod.schemaToOptionInfo(command.schema) : getCommandOptions(command);
|
|
410
410
|
command.optionsInfo = options;
|
|
411
411
|
return {
|
|
412
412
|
aliases: command.alias(),
|
package/dist/config.js
CHANGED
|
@@ -18,6 +18,7 @@ export default {
|
|
|
18
18
|
'https://graph.microsoft.com/Directory.ReadWrite.All',
|
|
19
19
|
'https://graph.microsoft.com/ExternalConnection.ReadWrite.All',
|
|
20
20
|
'https://graph.microsoft.com/ExternalItem.ReadWrite.All',
|
|
21
|
+
'https://graph.microsoft.com/FileStorageContainer.Selected',
|
|
21
22
|
'https://graph.microsoft.com/Group.ReadWrite.All',
|
|
22
23
|
'https://graph.microsoft.com/IdentityProvider.ReadWrite.All',
|
|
23
24
|
'https://graph.microsoft.com/InformationProtectionPolicy.Read',
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
-
};
|
|
6
|
-
var _AdaptiveCardSendCommand_instances, _AdaptiveCardSendCommand_initTelemetry, _AdaptiveCardSendCommand_initOptions, _AdaptiveCardSendCommand_initValidators, _AdaptiveCardSendCommand_initOptionSets;
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { globalOptionsZod } from '../../../Command.js';
|
|
7
3
|
import request from '../../../request.js';
|
|
4
|
+
import { optionsUtils } from '../../../utils/optionsUtils.js';
|
|
5
|
+
import { zod } from '../../../utils/zod.js';
|
|
8
6
|
import AnonymousCommand from '../../base/AnonymousCommand.js';
|
|
9
7
|
import commands from '../commands.js';
|
|
10
|
-
|
|
8
|
+
export const options = globalOptionsZod
|
|
9
|
+
.extend({
|
|
10
|
+
url: z.string(),
|
|
11
|
+
title: zod.alias('t', z.string().optional()),
|
|
12
|
+
description: zod.alias('d', z.string().optional()),
|
|
13
|
+
imageUrl: zod.alias('i', z.string().optional()),
|
|
14
|
+
actionUrl: zod.alias('a', z.string().optional()),
|
|
15
|
+
card: z.string().optional(),
|
|
16
|
+
cardData: z.string().optional()
|
|
17
|
+
})
|
|
18
|
+
.and(z.any());
|
|
11
19
|
class AdaptiveCardSendCommand extends AnonymousCommand {
|
|
12
20
|
get name() {
|
|
13
21
|
return commands.SEND;
|
|
@@ -15,19 +23,48 @@ class AdaptiveCardSendCommand extends AnonymousCommand {
|
|
|
15
23
|
get description() {
|
|
16
24
|
return 'Sends adaptive card to the specified URL';
|
|
17
25
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
_AdaptiveCardSendCommand_instances.add(this);
|
|
21
|
-
__classPrivateFieldGet(this, _AdaptiveCardSendCommand_instances, "m", _AdaptiveCardSendCommand_initTelemetry).call(this);
|
|
22
|
-
__classPrivateFieldGet(this, _AdaptiveCardSendCommand_instances, "m", _AdaptiveCardSendCommand_initOptions).call(this);
|
|
23
|
-
__classPrivateFieldGet(this, _AdaptiveCardSendCommand_instances, "m", _AdaptiveCardSendCommand_initValidators).call(this);
|
|
24
|
-
__classPrivateFieldGet(this, _AdaptiveCardSendCommand_instances, "m", _AdaptiveCardSendCommand_initOptionSets).call(this);
|
|
26
|
+
get schema() {
|
|
27
|
+
return options;
|
|
25
28
|
}
|
|
26
|
-
|
|
27
|
-
return
|
|
29
|
+
getRefinedSchema(schema) {
|
|
30
|
+
return schema
|
|
31
|
+
.refine(options => !options.cardData || options.card, {
|
|
32
|
+
message: 'When you specify cardData, you must also specify card.',
|
|
33
|
+
path: ['cardData']
|
|
34
|
+
})
|
|
35
|
+
.refine(options => {
|
|
36
|
+
if (options.card) {
|
|
37
|
+
try {
|
|
38
|
+
JSON.parse(options.card);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}, {
|
|
47
|
+
message: 'Specified card is not a valid JSON string.',
|
|
48
|
+
path: ['card']
|
|
49
|
+
})
|
|
50
|
+
.refine(options => {
|
|
51
|
+
if (options.cardData) {
|
|
52
|
+
try {
|
|
53
|
+
JSON.parse(options.cardData);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}, {
|
|
62
|
+
message: 'Specified cardData is not a valid JSON string.',
|
|
63
|
+
path: ['cardData']
|
|
64
|
+
});
|
|
28
65
|
}
|
|
29
66
|
async commandAction(logger, args) {
|
|
30
|
-
const unknownOptions = optionsUtils.getUnknownOptions(args.options, this.
|
|
67
|
+
const unknownOptions = optionsUtils.getUnknownOptions(args.options, zod.schemaToOptions(this.schema));
|
|
31
68
|
const unknownOptionNames = Object.getOwnPropertyNames(unknownOptions);
|
|
32
69
|
const card = await this.getCard(args, unknownOptionNames, unknownOptions);
|
|
33
70
|
const requestOptions = {
|
|
@@ -166,55 +203,5 @@ class AdaptiveCardSendCommand extends AnonymousCommand {
|
|
|
166
203
|
return cardData;
|
|
167
204
|
}
|
|
168
205
|
}
|
|
169
|
-
_AdaptiveCardSendCommand_instances = new WeakSet(), _AdaptiveCardSendCommand_initTelemetry = function _AdaptiveCardSendCommand_initTelemetry() {
|
|
170
|
-
this.telemetry.push((args) => {
|
|
171
|
-
Object.assign(this.telemetryProperties, {
|
|
172
|
-
actionUrl: typeof args.options.actionUrl !== 'undefined',
|
|
173
|
-
card: typeof args.options.card !== 'undefined',
|
|
174
|
-
cardData: typeof args.options.cardData !== 'undefined',
|
|
175
|
-
description: typeof args.options.description !== 'undefined',
|
|
176
|
-
imageUrl: typeof args.options.imageUrl !== 'undefined',
|
|
177
|
-
title: typeof args.options.title !== 'undefined'
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
}, _AdaptiveCardSendCommand_initOptions = function _AdaptiveCardSendCommand_initOptions() {
|
|
181
|
-
this.options.unshift({
|
|
182
|
-
option: '-u, --url <url>'
|
|
183
|
-
}, {
|
|
184
|
-
option: '-t, --title [title]'
|
|
185
|
-
}, {
|
|
186
|
-
option: '-d, --description [description]'
|
|
187
|
-
}, {
|
|
188
|
-
option: '-i, --imageUrl [imageUrl]'
|
|
189
|
-
}, {
|
|
190
|
-
option: '-a, --actionUrl [actionUrl]'
|
|
191
|
-
}, {
|
|
192
|
-
option: '--card [card]'
|
|
193
|
-
}, {
|
|
194
|
-
option: '--cardData [cardData]'
|
|
195
|
-
});
|
|
196
|
-
}, _AdaptiveCardSendCommand_initValidators = function _AdaptiveCardSendCommand_initValidators() {
|
|
197
|
-
this.validators.push(async (args) => {
|
|
198
|
-
if (args.options.card) {
|
|
199
|
-
try {
|
|
200
|
-
JSON.parse(args.options.card);
|
|
201
|
-
}
|
|
202
|
-
catch (e) {
|
|
203
|
-
return `Error while parsing the card: ${e}`;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
if (args.options.cardData) {
|
|
207
|
-
try {
|
|
208
|
-
JSON.parse(args.options.cardData);
|
|
209
|
-
}
|
|
210
|
-
catch (e) {
|
|
211
|
-
return `Error while parsing card data: ${e}`;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return true;
|
|
215
|
-
});
|
|
216
|
-
}, _AdaptiveCardSendCommand_initOptionSets = function _AdaptiveCardSendCommand_initOptionSets() {
|
|
217
|
-
this.optionSets.push({ options: ['title', 'card'] });
|
|
218
|
-
};
|
|
219
206
|
export default new AdaptiveCardSendCommand();
|
|
220
207
|
//# sourceMappingURL=adaptivecard-send.js.map
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import GraphCommand from '../../../base/GraphCommand.js';
|
|
2
|
+
import commands from '../../commands.js';
|
|
3
|
+
import auth from '../../../../Auth.js';
|
|
4
|
+
import config from '../../../../config.js';
|
|
5
|
+
import { urlUtil } from '../../../../utils/urlUtil.js';
|
|
6
|
+
import request from '../../../../request.js';
|
|
7
|
+
import { cli } from '../../../../cli/cli.js';
|
|
8
|
+
import { settingsNames } from '../../../../settingsNames.js';
|
|
9
|
+
import { browserUtil } from '../../../../utils/browserUtil.js';
|
|
10
|
+
import { entraApp } from '../../../../utils/entraApp.js';
|
|
11
|
+
import { entraServicePrincipal } from '../../../../utils/entraServicePrincipal.js';
|
|
12
|
+
class CliAppReconsentCommand extends GraphCommand {
|
|
13
|
+
get name() {
|
|
14
|
+
return commands.APP_RECONSENT;
|
|
15
|
+
}
|
|
16
|
+
get description() {
|
|
17
|
+
return 'Reconsent all permission scopes used in CLI for Microsoft 365';
|
|
18
|
+
}
|
|
19
|
+
async commandAction(logger) {
|
|
20
|
+
try {
|
|
21
|
+
const appId = auth.connection.appId;
|
|
22
|
+
if (this.verbose) {
|
|
23
|
+
await logger.logToStderr(`Adding all missing permission scopes used in CLI for Microsoft 365 to application with ID '${appId}'...`);
|
|
24
|
+
}
|
|
25
|
+
const application = await entraApp.getAppRegistrationByAppId(appId, ['requiredResourceAccess', 'id']);
|
|
26
|
+
await this.addCliAppScopes(logger, application.requiredResourceAccess);
|
|
27
|
+
await this.updateAppScopes(logger, application.id, application.requiredResourceAccess);
|
|
28
|
+
const consentUrl = `https://login.microsoftonline.com/${auth.connection.tenant}/adminconsent?client_id=${appId}`;
|
|
29
|
+
await logger.log(`To consent to the new scopes for your Microsoft Entra application registration, please navigate to the following URL: ${consentUrl}`);
|
|
30
|
+
if (cli.getSettingWithDefaultValue(settingsNames.autoOpenLinksInBrowser, false)) {
|
|
31
|
+
await browserUtil.open(consentUrl);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
this.handleRejectedODataJsonPromise(err);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async addCliAppScopes(logger, appScopes) {
|
|
39
|
+
const allCliScopes = config.allScopes;
|
|
40
|
+
const servicePrincipals = await entraServicePrincipal.getServicePrincipals('displayName,appId,oauth2PermissionScopes,servicePrincipalNames');
|
|
41
|
+
if (this.verbose) {
|
|
42
|
+
await logger.logToStderr(`Verifying if all ${allCliScopes.length} permission scopes are present in the app registration...`);
|
|
43
|
+
}
|
|
44
|
+
for (const cliScope of allCliScopes) {
|
|
45
|
+
// Extract service principal name and scope from the URL string
|
|
46
|
+
const spName = urlUtil.removeTrailingSlashes(cliScope.substring(0, cliScope.lastIndexOf('/')));
|
|
47
|
+
const scopeName = cliScope.substring(cliScope.lastIndexOf('/') + 1);
|
|
48
|
+
// Find the matching service principal by name
|
|
49
|
+
const servicePrincipal = servicePrincipals.find(sp => sp.servicePrincipalNames?.some(name => urlUtil.removeTrailingSlashes(name).toLowerCase() === spName.toLowerCase()));
|
|
50
|
+
if (!servicePrincipal) {
|
|
51
|
+
if (this.verbose) {
|
|
52
|
+
await logger.logToStderr(`Service principal with name '${spName}' not found. Skipping scope '${scopeName}'.`);
|
|
53
|
+
}
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
// Find the matching scope in the service principal
|
|
57
|
+
const scope = servicePrincipal.oauth2PermissionScopes?.find(s => s.value?.toLowerCase() === scopeName.toLowerCase());
|
|
58
|
+
if (!scope) {
|
|
59
|
+
if (this.verbose) {
|
|
60
|
+
await logger.logToStderr(`Scope '${scopeName}' not found in service principal '${spName}'. Skipping scope...`);
|
|
61
|
+
}
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
// Check if the service principal is already present in the app registration
|
|
65
|
+
let appSp = appScopes.find(sp => sp.resourceAppId?.toLowerCase() === servicePrincipal.appId.toLowerCase());
|
|
66
|
+
if (!appSp) {
|
|
67
|
+
// Service principal is not present in the app registration, let's add it
|
|
68
|
+
appSp = {
|
|
69
|
+
resourceAppId: servicePrincipal.appId,
|
|
70
|
+
resourceAccess: []
|
|
71
|
+
};
|
|
72
|
+
appScopes.push(appSp);
|
|
73
|
+
}
|
|
74
|
+
// Check if the scope is already present in the app registration
|
|
75
|
+
const isAppScopePresent = appSp.resourceAccess.some(s => s.id?.toLowerCase() === scope.id.toLowerCase());
|
|
76
|
+
if (!isAppScopePresent) {
|
|
77
|
+
// Scope is not present in the app registration, let's add it
|
|
78
|
+
appSp.resourceAccess.push({
|
|
79
|
+
id: scope.id,
|
|
80
|
+
type: 'Scope'
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async updateAppScopes(logger, appId, appScopes) {
|
|
86
|
+
if (this.verbose) {
|
|
87
|
+
await logger.logToStderr(`Updating permission scopes of application with ID '${appId}'...`);
|
|
88
|
+
}
|
|
89
|
+
const requestOptions = {
|
|
90
|
+
url: `${this.resource}/v1.0/applications/${appId}`,
|
|
91
|
+
headers: {
|
|
92
|
+
accept: 'application/json;odata.metadata=none'
|
|
93
|
+
},
|
|
94
|
+
responseType: 'json',
|
|
95
|
+
data: {
|
|
96
|
+
requiredResourceAccess: appScopes
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
await request.patch(requestOptions);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export default new CliAppReconsentCommand();
|
|
103
|
+
//# sourceMappingURL=app-reconsent.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const prefix = 'cli';
|
|
2
2
|
export default {
|
|
3
|
+
APP_RECONSENT: `${prefix} app reconsent`,
|
|
3
4
|
COMPLETION_CLINK_UPDATE: `${prefix} completion clink update`,
|
|
4
5
|
COMPLETION_PWSH_SETUP: `${prefix} completion pwsh setup`,
|
|
5
6
|
COMPLETION_PWSH_UPDATE: `${prefix} completion pwsh update`,
|
|
@@ -37,7 +37,7 @@ class LoginCommand extends Command {
|
|
|
37
37
|
}
|
|
38
38
|
getRefinedSchema(schema) {
|
|
39
39
|
return schema
|
|
40
|
-
.refine(options => typeof options.appId !== 'undefined' || cli.getClientId() || options.authType === 'identity', {
|
|
40
|
+
.refine(options => typeof options.appId !== 'undefined' || cli.getClientId() || options.authType === 'identity' || options.authType === 'federatedIdentity', {
|
|
41
41
|
message: `appId is required. TIP: use the "m365 setup" command to configure the default appId.`,
|
|
42
42
|
path: ['appId']
|
|
43
43
|
})
|
|
@@ -18,7 +18,6 @@ import { validation } from '../../utils/validation.js';
|
|
|
18
18
|
import AnonymousCommand from '../base/AnonymousCommand.js';
|
|
19
19
|
import commands from './commands.js';
|
|
20
20
|
import { interactivePreset, powerShellPreset, scriptingPreset } from './setupPresets.js';
|
|
21
|
-
import { optionsUtils } from '../../utils/optionsUtils.js';
|
|
22
21
|
export var CliUsageMode;
|
|
23
22
|
(function (CliUsageMode) {
|
|
24
23
|
CliUsageMode["Interactively"] = "interactively";
|
|
@@ -228,7 +227,7 @@ class SetupCommand extends AnonymousCommand {
|
|
|
228
227
|
});
|
|
229
228
|
const appInfo = await entraApp.createAppRegistration({
|
|
230
229
|
options,
|
|
231
|
-
unknownOptions:
|
|
230
|
+
unknownOptions: {},
|
|
232
231
|
apis,
|
|
233
232
|
logger,
|
|
234
233
|
verbose: this.verbose,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { globalOptionsZod } from '../../../../Command.js';
|
|
3
|
+
import { zod } from '../../../../utils/zod.js';
|
|
4
|
+
import GraphCommand from '../../../base/GraphCommand.js';
|
|
5
|
+
import commands from '../../commands.js';
|
|
6
|
+
import { odata } from '../../../../utils/odata.js';
|
|
7
|
+
const options = globalOptionsZod
|
|
8
|
+
.extend({
|
|
9
|
+
properties: zod.alias('p', z.string().optional())
|
|
10
|
+
})
|
|
11
|
+
.strict();
|
|
12
|
+
class EntraOrganizationListCommand extends GraphCommand {
|
|
13
|
+
get name() {
|
|
14
|
+
return commands.ORGANIZATION_LIST;
|
|
15
|
+
}
|
|
16
|
+
get description() {
|
|
17
|
+
return 'Lists all Microsoft Entra ID organizations';
|
|
18
|
+
}
|
|
19
|
+
defaultProperties() {
|
|
20
|
+
return ['id', 'displayName', 'tenantType'];
|
|
21
|
+
}
|
|
22
|
+
get schema() {
|
|
23
|
+
return options;
|
|
24
|
+
}
|
|
25
|
+
async commandAction(logger, args) {
|
|
26
|
+
try {
|
|
27
|
+
let url = `${this.resource}/v1.0/organization`;
|
|
28
|
+
if (args.options.properties) {
|
|
29
|
+
url += `?$select=${args.options.properties}`;
|
|
30
|
+
}
|
|
31
|
+
const requestOptions = {
|
|
32
|
+
url: url,
|
|
33
|
+
headers: {
|
|
34
|
+
accept: 'application/json;odata.metadata=none',
|
|
35
|
+
'content-type': 'application/json'
|
|
36
|
+
},
|
|
37
|
+
responseType: 'json'
|
|
38
|
+
};
|
|
39
|
+
if (args.options.verbose) {
|
|
40
|
+
await logger.logToStderr(`Retrieving organizations...`);
|
|
41
|
+
}
|
|
42
|
+
const res = await odata.getAllItems(requestOptions);
|
|
43
|
+
await logger.log(res);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
this.handleRejectedODataJsonPromise(err);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export default new EntraOrganizationListCommand();
|
|
51
|
+
//# sourceMappingURL=organization-list.js.map
|
|
@@ -83,6 +83,7 @@ export default {
|
|
|
83
83
|
OAUTH2GRANT_LIST: `${prefix} oauth2grant list`,
|
|
84
84
|
OAUTH2GRANT_REMOVE: `${prefix} oauth2grant remove`,
|
|
85
85
|
OAUTH2GRANT_SET: `${prefix} oauth2grant set`,
|
|
86
|
+
ORGANIZATION_LIST: `${prefix} organization list`,
|
|
86
87
|
PIM_ROLE_ASSIGNMENT_ADD: `${prefix} pim role assignment add`,
|
|
87
88
|
PIM_ROLE_ASSIGNMENT_LIST: `${prefix} pim role assignment list`,
|
|
88
89
|
PIM_ROLE_ASSIGNMENT_REMOVE: `${prefix} pim role assignment remove`,
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { globalOptionsZod } from '../../../../Command.js';
|
|
3
|
+
import { zod } from '../../../../utils/zod.js';
|
|
4
|
+
import { validation } from '../../../../utils/validation.js';
|
|
5
|
+
import GraphCommand from '../../../base/GraphCommand.js';
|
|
6
|
+
import commands from '../../commands.js';
|
|
7
|
+
import request from '../../../../request.js';
|
|
8
|
+
import { optionsUtils } from '../../../../utils/optionsUtils.js';
|
|
9
|
+
const options = globalOptionsZod
|
|
10
|
+
.extend({
|
|
11
|
+
name: zod.alias('n', z.string()),
|
|
12
|
+
resourceId: zod.alias('i', z.string()),
|
|
13
|
+
resourceType: zod.alias('t', z.enum(['user', 'group', 'device', 'organization'])),
|
|
14
|
+
keepUnchangedProperties: zod.alias('k', z.boolean().optional())
|
|
15
|
+
})
|
|
16
|
+
.and(z.any());
|
|
17
|
+
class GraphOpenExtensionSetCommand extends GraphCommand {
|
|
18
|
+
constructor() {
|
|
19
|
+
super(...arguments);
|
|
20
|
+
this.commandOptions = ['keepUnchangedProperties', 'resourceType', 'resourceId', 'name'];
|
|
21
|
+
this.defaultOpenExtensionProperties = ['id', 'extensionName'];
|
|
22
|
+
}
|
|
23
|
+
get name() {
|
|
24
|
+
return commands.OPENEXTENSION_SET;
|
|
25
|
+
}
|
|
26
|
+
get description() {
|
|
27
|
+
return 'Updates an open extension for a resource';
|
|
28
|
+
}
|
|
29
|
+
get schema() {
|
|
30
|
+
return options;
|
|
31
|
+
}
|
|
32
|
+
getRefinedSchema(schema) {
|
|
33
|
+
return schema
|
|
34
|
+
.refine(options => options.resourceType !== 'group' && options.resourceType !== 'device' && options.resourceType !== 'organization' || (options.resourceId && validation.isValidGuid(options.resourceId)), options => ({
|
|
35
|
+
message: `The '${options.resourceId}' must be a valid GUID`,
|
|
36
|
+
path: ['resourceId']
|
|
37
|
+
}))
|
|
38
|
+
.refine(options => options.resourceType !== 'user' || (options.resourceId && (validation.isValidGuid(options.resourceId) || validation.isValidUserPrincipalName(options.resourceId))), options => ({
|
|
39
|
+
message: `The '${options.resourceId}' must be a valid GUID or user principal name`,
|
|
40
|
+
path: ['resourceId']
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
async commandAction(logger, args) {
|
|
44
|
+
try {
|
|
45
|
+
const currentExtension = await this.getOpenExtension(logger, args);
|
|
46
|
+
const currentExtensionNames = Object.getOwnPropertyNames(currentExtension);
|
|
47
|
+
const requestBody = {};
|
|
48
|
+
requestBody["@odata.type"] = '#microsoft.graph.openTypeExtension';
|
|
49
|
+
const unknownOptions = optionsUtils.getUnknownOptions(args.options, this.options);
|
|
50
|
+
const unknownOptionsNames = Object.getOwnPropertyNames(unknownOptions);
|
|
51
|
+
unknownOptionsNames.forEach(async (option) => {
|
|
52
|
+
if (this.commandOptions.includes(option)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const value = unknownOptions[option];
|
|
56
|
+
if (value === "") {
|
|
57
|
+
requestBody[option] = null;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
try {
|
|
61
|
+
const jsonObject = JSON.parse(value);
|
|
62
|
+
requestBody[option] = jsonObject;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
requestBody[option] = value;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
currentExtensionNames.forEach(async (name) => {
|
|
70
|
+
if (!unknownOptionsNames.includes(name) && (args.options.keepUnchangedProperties || this.defaultOpenExtensionProperties.includes(name))) {
|
|
71
|
+
requestBody[name] = currentExtension[name];
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
const requestOptions = {
|
|
75
|
+
url: `${this.resource}/v1.0/${args.options.resourceType}${args.options.resourceType === 'organization' ? '' : 's'}/${args.options.resourceId}/extensions/${args.options.name}`,
|
|
76
|
+
headers: {
|
|
77
|
+
accept: 'application/json;odata.metadata=none',
|
|
78
|
+
'content-type': 'application/json'
|
|
79
|
+
},
|
|
80
|
+
data: requestBody,
|
|
81
|
+
responseType: 'json'
|
|
82
|
+
};
|
|
83
|
+
if (args.options.verbose) {
|
|
84
|
+
await logger.logToStderr(`Updating open extension of the ${args.options.resourceType} with id '${args.options.resourceId}'...`);
|
|
85
|
+
}
|
|
86
|
+
await request.patch(requestOptions);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
this.handleRejectedODataJsonPromise(err);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async getOpenExtension(logger, args) {
|
|
93
|
+
if (this.verbose) {
|
|
94
|
+
await logger.logToStderr(`Retrieving open extension for resource ${args.options.resourceId}...`);
|
|
95
|
+
}
|
|
96
|
+
const requestOptions = {
|
|
97
|
+
url: `${this.resource}/v1.0/${args.options.resourceType}${args.options.resourceType === 'organization' ? '' : 's'}/${args.options.resourceId}/extensions/${args.options.name}`,
|
|
98
|
+
headers: {
|
|
99
|
+
accept: 'application/json;odata.metadata=none'
|
|
100
|
+
},
|
|
101
|
+
responseType: 'json'
|
|
102
|
+
};
|
|
103
|
+
return await request.get(requestOptions);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export default new GraphOpenExtensionSetCommand();
|
|
107
|
+
//# sourceMappingURL=openextension-set.js.map
|
|
@@ -8,6 +8,7 @@ export default {
|
|
|
8
8
|
OPENEXTENSION_GET: `${prefix} openextension get`,
|
|
9
9
|
OPENEXTENSION_LIST: `${prefix} openextension list`,
|
|
10
10
|
OPENEXTENSION_REMOVE: `${prefix} openextension remove`,
|
|
11
|
+
OPENEXTENSION_SET: `${prefix} openextension set`,
|
|
11
12
|
SCHEMAEXTENSION_ADD: `${prefix} schemaextension add`,
|
|
12
13
|
SCHEMAEXTENSION_GET: `${prefix} schemaextension get`,
|
|
13
14
|
SCHEMAEXTENSION_LIST: `${prefix} schemaextension list`,
|