diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 6a4f107a168..931de61f390 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -32,6 +32,7 @@ const dictionary = [
'customizer',
'dataverse',
'default',
+ 'definition',
'dev',
'details',
'eligibility',
diff --git a/docs/docs/cmd/entra/roledefinition/roledefinition-list.mdx b/docs/docs/cmd/entra/roledefinition/roledefinition-list.mdx
new file mode 100644
index 00000000000..b41473b1246
--- /dev/null
+++ b/docs/docs/cmd/entra/roledefinition/roledefinition-list.mdx
@@ -0,0 +1,148 @@
+import Global from '/docs/cmd/_global.mdx';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# entra roledefinition list
+
+Lists all Microsoft Entra ID role definitions.
+
+## Usage
+
+```sh
+m365 entra roledefinition list [options]
+```
+
+## Options
+
+```md definition-list
+`-p, --properties [properties]`
+: Comma-separated list of properties to retrieve.
+
+`-f, --filter [filter]`
+: OData filter to apply when retrieving the role definitions.
+```
+
+
+
+## Examples
+
+Retrieve all Microsoft Entra ID role definitions
+
+```sh
+m365 entra roledefinition list
+```
+
+Retrieve only the names of the role definitions
+
+```sh
+m365 entra roledefinition list --properties 'displayName'
+```
+
+Retrieve only custom role definitions
+
+```sh
+m365 entra roledefinition list --filter 'isBuiltIn eq false'
+```
+
+## Response
+
+### Standard response
+
+
+
+
+ ```json
+ [
+ {
+ "id": "f28a1f50-f6e7-4571-818b-6a12f2af6b6c",
+ "description": "Can manage all aspects of the SharePoint service.",
+ "displayName": "SharePoint Administrator",
+ "isBuiltIn": true,
+ "isEnabled": true,
+ "resourceScopes": [
+ "/"
+ ],
+ "templateId": "f28a1f50-f6e7-4571-818b-6a12f2af6b6c",
+ "version": "1",
+ "rolePermissions": [
+ {
+ "allowedResourceActions": [
+ "microsoft.azure.serviceHealth/allEntities/allTasks",
+ "microsoft.azure.supportTickets/allEntities/allTasks",
+ "microsoft.backup/oneDriveForBusinessProtectionPolicies/allProperties/allTasks",
+ "microsoft.backup/oneDriveForBusinessRestoreSessions/allProperties/allTasks",
+ "microsoft.backup/restorePoints/sites/allProperties/allTasks",
+ "microsoft.backup/restorePoints/userDrives/allProperties/allTasks",
+ "microsoft.backup/sharePointProtectionPolicies/allProperties/allTasks",
+ "microsoft.backup/sharePointRestoreSessions/allProperties/allTasks",
+ "microsoft.backup/siteProtectionUnits/allProperties/allTasks",
+ "microsoft.backup/siteRestoreArtifacts/allProperties/allTasks",
+ "microsoft.backup/userDriveProtectionUnits/allProperties/allTasks",
+ "microsoft.backup/userDriveRestoreArtifacts/allProperties/allTasks",
+ "microsoft.directory/groups/hiddenMembers/read",
+ "microsoft.directory/groups.unified/basic/update",
+ "microsoft.directory/groups.unified/create",
+ "microsoft.directory/groups.unified/delete",
+ "microsoft.directory/groups.unified/members/update",
+ "microsoft.directory/groups.unified/owners/update",
+ "microsoft.directory/groups.unified/restore",
+ "microsoft.office365.migrations/allEntities/allProperties/allTasks",
+ "microsoft.office365.network/performance/allProperties/read",
+ "microsoft.office365.serviceHealth/allEntities/allTasks",
+ "microsoft.office365.sharePoint/allEntities/allTasks",
+ "microsoft.office365.supportTickets/allEntities/allTasks",
+ "microsoft.office365.usageReports/allEntities/allProperties/read",
+ "microsoft.office365.webPortal/allEntities/standard/read"
+ ],
+ "condition": null
+ }
+ ],
+ "inheritsPermissionsFrom": [
+ {
+ "id": "88d8e3e3-8f55-4a1e-953a-9b9898b8876b"
+ }
+ ]
+ }
+ ]
+ ```
+
+
+
+
+ ```text
+ id displayName isBuiltIn isEnabled
+ ------------------------------------ --------------------------------------------- --------- ---------
+ f28a1f50-f6e7-4571-818b-6a12f2af6b6c SharePoint Administrator true true
+ ```
+
+
+
+
+ ```csv
+ id,description,displayName,isBuiltIn,isEnabled,templateId,version
+ f28a1f50-f6e7-4571-818b-6a12f2af6b6c,Can manage all aspects of the SharePoint service.,SharePoint Administrator,1,1,f28a1f50-f6e7-4571-818b-6a12f2af6b6c,1
+ ```
+
+
+
+
+ ```md
+ # entra roledefinition list
+
+ Date: 11/7/2024
+
+ ## SharePoint Administrator (f28a1f50-f6e7-4571-818b-6a12f2af6b6c)
+
+ Property | Value
+ ---------|-------
+ id | f28a1f50-f6e7-4571-818b-6a12f2af6b6c
+ description | Can manage all aspects of the SharePoint service.
+ displayName | SharePoint Administrator
+ isBuiltIn | true
+ isEnabled | true
+ templateId | f28a1f50-f6e7-4571-818b-6a12f2af6b6c
+ version | 1
+ ```
+
+
+
diff --git a/docs/src/config/sidebars.ts b/docs/src/config/sidebars.ts
index 06ed8558b56..acf13bcd47b 100644
--- a/docs/src/config/sidebars.ts
+++ b/docs/src/config/sidebars.ts
@@ -627,6 +627,15 @@ const sidebars: SidebarsConfig = {
}
]
},
+ {
+ roledefinition: [
+ {
+ type: 'doc',
+ label: 'roledefinition list',
+ id: 'cmd/entra/roledefinition/roledefinition-list'
+ }
+ ]
+ },
{
siteclassification: [
{
diff --git a/src/m365/entra/commands.ts b/src/m365/entra/commands.ts
index 4b51b5d02e4..bf397c5f31d 100644
--- a/src/m365/entra/commands.ts
+++ b/src/m365/entra/commands.ts
@@ -88,6 +88,7 @@ export default {
PIM_ROLE_ASSIGNMENT_ELIGIBILITY_LIST: `${prefix} pim role assignment eligibility list`,
PIM_ROLE_REQUEST_LIST: `${prefix} pim role request list`,
POLICY_LIST: `${prefix} policy list`,
+ ROLEDEFINITION_LIST: `${prefix} roledefinition list`,
SITECLASSIFICATION_DISABLE: `${prefix} siteclassification disable`,
SITECLASSIFICATION_ENABLE: `${prefix} siteclassification enable`,
SITECLASSIFICATION_GET: `${prefix} siteclassification get`,
diff --git a/src/m365/entra/commands/roledefinition/roledefinition-list.spec.ts b/src/m365/entra/commands/roledefinition/roledefinition-list.spec.ts
new file mode 100644
index 00000000000..e6e1520c7f0
--- /dev/null
+++ b/src/m365/entra/commands/roledefinition/roledefinition-list.spec.ts
@@ -0,0 +1,241 @@
+import assert from 'assert';
+import sinon from 'sinon';
+import auth from '../../../../Auth.js';
+import commands from '../../commands.js';
+import request from '../../../../request.js';
+import { Logger } from '../../../../cli/Logger.js';
+import { telemetry } from '../../../../telemetry.js';
+import { pid } from '../../../../utils/pid.js';
+import { session } from '../../../../utils/session.js';
+import command from './roledefinition-list.js';
+import { sinonUtil } from '../../../../utils/sinonUtil.js';
+import { CommandError } from '../../../../Command.js';
+
+describe(commands.ROLEDEFINITION_LIST, () => {
+ const roleDefinitionsResponse = [
+ {
+ "id": "f28a1f50-f6e7-4571-818b-6a12f2af6b6c",
+ "description": "Can manage all aspects of the SharePoint service.",
+ "displayName": "SharePoint Administrator",
+ "isBuiltIn": true,
+ "isEnabled": true,
+ "resourceScopes": [
+ "/"
+ ],
+ "templateId": "f28a1f50-f6e7-4571-818b-6a12f2af6b6c",
+ "version": "1",
+ "rolePermissions": [
+ {
+ "allowedResourceActions": [
+ "microsoft.azure.serviceHealth/allEntities/allTasks",
+ "microsoft.azure.supportTickets/allEntities/allTasks",
+ "microsoft.backup/oneDriveForBusinessProtectionPolicies/allProperties/allTasks",
+ "microsoft.backup/oneDriveForBusinessRestoreSessions/allProperties/allTasks",
+ "microsoft.backup/restorePoints/sites/allProperties/allTasks",
+ "microsoft.backup/restorePoints/userDrives/allProperties/allTasks",
+ "microsoft.backup/sharePointProtectionPolicies/allProperties/allTasks",
+ "microsoft.backup/sharePointRestoreSessions/allProperties/allTasks",
+ "microsoft.backup/siteProtectionUnits/allProperties/allTasks",
+ "microsoft.backup/siteRestoreArtifacts/allProperties/allTasks",
+ "microsoft.backup/userDriveProtectionUnits/allProperties/allTasks",
+ "microsoft.backup/userDriveRestoreArtifacts/allProperties/allTasks",
+ "microsoft.directory/groups/hiddenMembers/read",
+ "microsoft.directory/groups.unified/basic/update",
+ "microsoft.directory/groups.unified/create",
+ "microsoft.directory/groups.unified/delete",
+ "microsoft.directory/groups.unified/members/update",
+ "microsoft.directory/groups.unified/owners/update",
+ "microsoft.directory/groups.unified/restore",
+ "microsoft.office365.migrations/allEntities/allProperties/allTasks",
+ "microsoft.office365.network/performance/allProperties/read",
+ "microsoft.office365.serviceHealth/allEntities/allTasks",
+ "microsoft.office365.sharePoint/allEntities/allTasks",
+ "microsoft.office365.supportTickets/allEntities/allTasks",
+ "microsoft.office365.usageReports/allEntities/allProperties/read",
+ "microsoft.office365.webPortal/allEntities/standard/read"
+ ],
+ "condition": null
+ }
+ ],
+ "inheritsPermissionsFrom": [
+ {
+ "id": "88d8e3e3-8f55-4a1e-953a-9b9898b8876b"
+ }
+ ]
+ },
+ {
+ "id": "abcd1234-de71-4623-b4af-96380a352509",
+ "description": "Can read Bitlocker keys.",
+ "displayName": "Bitlocker Keys Reader",
+ "isBuiltIn": false,
+ "isEnabled": true,
+ "resourceScopes": [
+ "/"
+ ],
+ "templateId": "abcd1234-de71-4623-b4af-96380a352509",
+ "version": "1",
+ "rolePermissions": [
+ {
+ "allowedResourceActions": [
+ "microsoft.directory/bitlockerKeys/key/read"
+ ],
+ "condition": null
+ }
+ ],
+ "inheritsPermissionsFrom": [
+ ]
+ }
+ ];
+
+ const roleDefinitionsLimitedResponse = [
+ {
+ "id": "f28a1f50-f6e7-4571-818b-6a12f2af6b6c",
+ "displayName": "SharePoint Administrator",
+ "isBuiltIn": true,
+ "isEnabled": true
+ },
+ {
+ "id": "abcd1234-de71-4623-b4af-96380a352509",
+ "displayName": "Bitlocker Keys Reader",
+ "isBuiltIn": false,
+ "isEnabled": true
+ }
+ ];
+
+ let log: string[];
+ let logger: Logger;
+ let loggerLogSpy: sinon.SinonSpy;
+
+ before(() => {
+ sinon.stub(auth, 'restoreAuth').resolves();
+ sinon.stub(telemetry, 'trackEvent').returns();
+ sinon.stub(pid, 'getProcessName').returns('');
+ sinon.stub(session, 'getId').returns('');
+ auth.connection.active = true;
+ });
+
+ beforeEach(() => {
+ log = [];
+ logger = {
+ log: async (msg: string) => {
+ log.push(msg);
+ },
+ logRaw: async (msg: string) => {
+ log.push(msg);
+ },
+ logToStderr: async (msg: string) => {
+ log.push(msg);
+ }
+ };
+ loggerLogSpy = sinon.spy(logger, 'log');
+ });
+
+ afterEach(() => {
+ sinonUtil.restore([
+ request.get
+ ]);
+ });
+
+ after(() => {
+ sinon.restore();
+ auth.connection.active = false;
+ });
+
+ it('has correct name', () => {
+ assert.strictEqual(command.name, commands.ROLEDEFINITION_LIST);
+ });
+
+ it('has a description', () => {
+ assert.notStrictEqual(command.description, null);
+ });
+
+ it('defines correct properties for the default output', () => {
+ assert.deepStrictEqual(command.defaultProperties(), ['id', 'displayName', 'isBuiltIn', 'isEnabled']);
+ });
+
+ it(`should get a list of Entra ID role definitions`, async () => {
+ sinon.stub(request, 'get').callsFake(async (opts) => {
+ if (opts.url === `https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions`) {
+ return {
+ value: roleDefinitionsResponse
+ };
+ }
+
+ throw 'Invalid request';
+ });
+
+ await command.action(logger, {
+ options: { verbose: true }
+ });
+
+ assert(loggerLogSpy.calledWith(roleDefinitionsResponse));
+ });
+
+ it(`should get a list of Entra ID role definitions with specified properties`, async () => {
+ sinon.stub(request, 'get').callsFake(async (opts) => {
+ if (opts.url === `https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions?$select=id,displayName,isBuiltIn,isEnabled`) {
+ return {
+ value: roleDefinitionsLimitedResponse
+ };
+ }
+
+ throw 'Invalid request';
+ });
+
+ await command.action(logger, {
+ options: { properties: 'id,displayName,isBuiltIn,isEnabled' }
+ });
+
+ assert(loggerLogSpy.calledWith(roleDefinitionsLimitedResponse));
+ });
+
+ it(`should get a list of filtered Entra ID role definitions`, async () => {
+ sinon.stub(request, 'get').callsFake(async (opts) => {
+ if (opts.url === `https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions?$filter=isBuiltIn eq false`) {
+ return {
+ value: [roleDefinitionsResponse[1]]
+ };
+ }
+
+ throw 'Invalid request';
+ });
+
+ await command.action(logger, {
+ options: { filter: 'isBuiltIn eq false' }
+ });
+
+ assert(loggerLogSpy.calledWith([roleDefinitionsResponse[1]]));
+ });
+
+ it(`should get a list of filtered Entra ID role definitions with specified properties`, async () => {
+ sinon.stub(request, 'get').callsFake(async (opts) => {
+ if (opts.url === `https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions?$select=id,displayName,isBuiltIn,isEnabled&$filter=isBuiltIn eq false`) {
+ return {
+ value: [roleDefinitionsLimitedResponse[1]]
+ };
+ }
+
+ throw 'Invalid request';
+ });
+
+ await command.action(logger, {
+ options: { properties: 'id,displayName,isBuiltIn,isEnabled', filter: 'isBuiltIn eq false' }
+ });
+
+ assert(loggerLogSpy.calledWith([roleDefinitionsLimitedResponse[1]]));
+ });
+
+ it('handles error when retrieving role definitions failed', async () => {
+ sinon.stub(request, 'get').callsFake(async (opts) => {
+ if (opts.url === `https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions`) {
+ throw { error: { message: 'An error has occurred' } };
+ }
+ throw `Invalid request`;
+ });
+
+ await assert.rejects(
+ command.action(logger, { options: {} } as any),
+ new CommandError('An error has occurred')
+ );
+ });
+});
\ No newline at end of file
diff --git a/src/m365/entra/commands/roledefinition/roledefinition-list.ts b/src/m365/entra/commands/roledefinition/roledefinition-list.ts
new file mode 100644
index 00000000000..846291ef071
--- /dev/null
+++ b/src/m365/entra/commands/roledefinition/roledefinition-list.ts
@@ -0,0 +1,69 @@
+import { UnifiedRoleDefinition } from '@microsoft/microsoft-graph-types';
+import { Logger } from '../../../../cli/Logger.js';
+import { odata } from '../../../../utils/odata.js';
+import GraphCommand from '../../../base/GraphCommand.js';
+import commands from '../../commands.js';
+import { z } from 'zod';
+import { globalOptionsZod } from '../../../../Command.js';
+import { zod } from '../../../../utils/zod.js';
+
+const options = globalOptionsZod
+ .extend({
+ properties: zod.alias('p', z.string().optional()),
+ filter: zod.alias('f', z.string().optional())
+ })
+ .strict();
+
+declare type Options = z.infer;
+
+interface CommandArgs {
+ options: Options;
+}
+
+class EntraRoleDefinitionListCommand extends GraphCommand {
+ public get name(): string {
+ return commands.ROLEDEFINITION_LIST;
+ }
+
+ public get description(): string {
+ return 'Lists all Microsoft Entra ID role definitions';
+ }
+
+ public defaultProperties(): string[] | undefined {
+ return ['id', 'displayName', 'isBuiltIn', 'isEnabled'];
+ }
+
+ public get schema(): z.ZodTypeAny | undefined {
+ return options;
+ }
+
+ public async commandAction(logger: Logger, args: CommandArgs): Promise {
+ if (this.verbose) {
+ await logger.logToStderr('Getting Microsoft Entra ID role definitions...');
+ }
+
+ try {
+ const queryParameters: string[] = [];
+
+ if (args.options.properties) {
+ queryParameters.push(`$select=${args.options.properties}`);
+ }
+
+ if (args.options.filter) {
+ queryParameters.push(`$filter=${args.options.filter}`);
+ }
+
+ const queryString = queryParameters.length > 0
+ ? `?${queryParameters.join('&')}`
+ : '';
+
+ const results = await odata.getAllItems(`${this.resource}/v1.0/roleManagement/directory/roleDefinitions${queryString}`);
+ await logger.log(results);
+ }
+ catch (err: any) {
+ this.handleRejectedODataJsonPromise(err);
+ }
+ }
+}
+
+export default new EntraRoleDefinitionListCommand();
\ No newline at end of file