Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions docs/docs/cmd/entra/agent/agent-blueprintprincipal-list.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import Global from '../../_global.mdx';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# entra agent blueprintprincipal list

Retrieves a list of agent blueprint principals

## Usage

```sh
m365 entra agent blueprintprincipal list [options]
```

## Options

```md definition-list
`-p, --properties [properties]`
: Comma-separated list of properties to retrieve.
```

<Global />

## Remarks

Using the `--properties` option, you can specify a comma-separated list of agent blueprint principal properties to retrieve from the Microsoft Graph. If you don't specify any properties, the command will output the default properties returned by Graph.

## Permissions

<Tabs>
<TabItem value="Delegated">

| Resource | Permissions |
|-----------------|------------------------------------------|
| Microsoft Graph | AgentIdentityBlueprintPrincipal.Read.All |

</TabItem>
<TabItem value="Application">

| Resource | Permissions |
|-----------------|------------------------------------------|
| Microsoft Graph | AgentIdentityBlueprintPrincipal.Read.All |

</TabItem>
</Tabs>

## Examples

Retrieve all agent blueprint principals

```sh
m365 entra agent blueprintprincipal list
```

Retrieve id and name of agent blueprint principals

```sh
m365 entra agent blueprintprincipal list --properties 'id,appDisplayName'
```

## Response

<Tabs>
<TabItem value="JSON">

```json
[
{
"accountEnabled": true,
"appDescription": null,
"appDisplayName": "OcnAgentBluePrint02",
"appId": "0e81af7f-b058-470a-84be-3a4f5a8014ca",
"appOwnerOrganizationId": "70cf0eca-e1e8-4d78-9d03-62ecf811dfc2",
"appRoleAssignmentRequired": false,
"createdByAppId": "14d82eec-204b-4c2f-b7e8-296a70dab67e",
"disabledByMicrosoftStatus": null,
"displayName": "OcnAgentBluePrint02",
"servicePrincipalNames": [
"0e81af7f-b058-470a-84be-3a4f5a8014ca"
],
"servicePrincipalType": "Application",
"signInAudience": "AzureADMyOrg",
"tags": [],
"id": "59246ef4-b832-48eb-a5e0-87748132e12c",
"appRoles": [],
"info": {
"logoUrl": null,
"marketingUrl": null,
"privacyStatementUrl": null,
"supportUrl": null,
"termsOfServiceUrl": null
},
"oauth2PermissionScopes": [],
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
]
```

</TabItem>
<TabItem value="Text">

```text
id appDisplayName appId
------------------------------------ ------------------- ------------------------------------
59246ef4-b832-48eb-a5e0-87748132e12c OcnAgentBluePrint02 0e81af7f-b058-470a-84be-3a4f5a8014ca
```

</TabItem>
<TabItem value="CSV">

```csv
accountEnabled,appDescription,appDisplayName,appId,appOwnerOrganizationId,appRoleAssignmentRequired,createdByAppId,disabledByMicrosoftStatus,displayName,servicePrincipalType,signInAudience,id
1,,OcnAgentBluePrint02,0e81af7f-b058-470a-84be-3a4f5a8014ca,70cf0eca-e1e8-4d78-9d03-62ecf811dfc2,0,14d82eec-204b-4c2f-b7e8-296a70dab67e,,OcnAgentBluePrint02,Application,AzureADMyOrg,59246ef4-b832-48eb-a5e0-87748132e12c
```

</TabItem>
<TabItem value="Markdown">

```md
# entra agent blueprintprincipal list --debug "false" --verbose "false"

Date: 6/5/2026

## OcnAgentBluePrint02 (59246ef4-b832-48eb-a5e0-87748132e12c)

Property | Value
---------|-------
accountEnabled | true
appDisplayName | OcnAgentBluePrint02
appId | 0e81af7f-b058-470a-84be-3a4f5a8014ca
appOwnerOrganizationId | 70cf0eca-e1e8-4d78-9d03-62ecf811dfc2
appRoleAssignmentRequired | false
createdByAppId | 14d82eec-204b-4c2f-b7e8-296a70dab67e
displayName | OcnAgentBluePrint02
servicePrincipalType | Application
signInAudience | AzureADMyOrg
id | 59246ef4-b832-48eb-a5e0-87748132e12c
```

</TabItem>
</Tabs>
9 changes: 9 additions & 0 deletions docs/src/config/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,15 @@ const sidebars: SidebarsConfig = {
}
]
},
{
agent: [
{
type: 'doc',
label: 'agent blueprintprincipal list',
id: 'cmd/entra/agent/agent-blueprintprincipal-list'
}
]
},
{
app: [
{
Expand Down
2 changes: 2 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const dictionary = [
'activations',
'adaptive',
'administrative',
'agent',
'ai',
'app',
'application',
Expand All @@ -26,6 +27,7 @@ const dictionary = [
'autofill',
'azure',
'bin',
'blueprintprincipal',
'brand',
'builder',
'calendar',
Expand Down
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export default {
allScopes: [
'https://management.azure.com/user_impersonation',
'https://admin.services.crm.dynamics.com/user_impersonation',
'https://graph.microsoft.com/AgentIdentityBlueprintPrincipal.Read.All',
'https://graph.microsoft.com/AppCatalog.ReadWrite.All',
'https://graph.microsoft.com/AuditLog.Read.All',
'https://graph.microsoft.com/Bookings.Read.All',
Expand Down
1 change: 1 addition & 0 deletions src/m365/entra/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default {
ADMINISTRATIVEUNIT_MEMBER_LIST: `${prefix} administrativeunit member list`,
ADMINISTRATIVEUNIT_MEMBER_REMOVE: `${prefix} administrativeunit member remove`,
ADMINISTRATIVEUNIT_ROLEASSIGNMENT_ADD: `${prefix} administrativeunit roleassignment add`,
AGENT_BLUEPRINTPRINCIPAL_LIST: `${prefix} agent blueprintprincipal list`,
APP_ADD: `${prefix} app add`,
APP_GET: `${prefix} app get`,
APP_LIST: `${prefix} app list`,
Expand Down
163 changes: 163 additions & 0 deletions src/m365/entra/commands/agent/agent-blueprintprincipal-list.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import assert from 'assert';
import sinon from 'sinon';
import auth from '../../../../Auth.js';
import { cli } from '../../../../cli/cli.js';
import { CommandInfo } from '../../../../cli/CommandInfo.js';
import { Logger } from '../../../../cli/Logger.js';
import { CommandError } from '../../../../Command.js';
import request from '../../../../request.js';
import { telemetry } from '../../../../telemetry.js';
import { pid } from '../../../../utils/pid.js';
import { session } from '../../../../utils/session.js';
import { sinonUtil } from '../../../../utils/sinonUtil.js';
import commands from '../../commands.js';
import command, { options } from './agent-blueprintprincipal-list.js';

describe(commands.AGENT_BLUEPRINTPRINCIPAL_LIST, () => {
let log: string[];
let logger: Logger;
let loggerLogSpy: sinon.SinonSpy;
let commandInfo: CommandInfo;
let commandOptionsSchema: typeof options;

const response = [
{
"accountEnabled": true,
"appDescription": null,
"appDisplayName": "OcnAgentBluePrint02",
"appId": "0e81af7f-b058-470a-84be-3a4f5a8014ca",
"appOwnerOrganizationId": "70cf0eca-e1e8-4d78-9d03-62ecf811dfc2",
"appRoleAssignmentRequired": false,
"createdByAppId": "14d82eec-204b-4c2f-b7e8-296a70dab67e",
"disabledByMicrosoftStatus": null,
"displayName": "OcnAgentBluePrint02",
"servicePrincipalNames": [
"0e81af7f-b058-470a-84be-3a4f5a8014ca"
],
"servicePrincipalType": "Application",
"signInAudience": "AzureADMyOrg",
"tags": [],
"id": "59246ef4-b832-48eb-a5e0-87748132e12c",
"appRoles": [],
"info": {
"logoUrl": null,
"marketingUrl": null,
"privacyStatementUrl": null,
"supportUrl": null,
"termsOfServiceUrl": null
},
"oauth2PermissionScopes": [],
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
];

const limitedResponse = [
{
"id": "59246ef4-b832-48eb-a5e0-87748132e12c",
"appDisplayName": "OcnAgentBluePrint02"
}
];

before(() => {
sinon.stub(auth, 'restoreAuth').resolves();
sinon.stub(telemetry, 'trackEvent').resolves();
sinon.stub(pid, 'getProcessName').returns('');
sinon.stub(session, 'getId').returns('');
auth.connection.active = true;
commandInfo = cli.getCommandInfo(command);
commandOptionsSchema = commandInfo.command.getSchemaToParse() as typeof options;
});

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.AGENT_BLUEPRINTPRINCIPAL_LIST);
});

it('has a description', () => {
assert.notStrictEqual(command.description, null);
});

it('defines correct properties for the default output', () => {
assert.deepStrictEqual(command.defaultProperties(), ['id', 'appDisplayName', 'appId']);
});

it(`should get a list of agent identity blueprints`, async () => {
sinon.stub(request, 'get').callsFake(async (opts) => {
if (opts.url === `https://graph.microsoft.com/v1.0/servicePrincipals/microsoft.graph.agentIdentityBlueprintPrincipal`) {
return {
value: response
};
}

throw 'Invalid request';
});

await command.action(logger, { options: commandOptionsSchema.parse({}) });

assert(
loggerLogSpy.calledWith(response)
);
});

it(`should get a list of administrative units with specified properties`, async () => {
sinon.stub(request, 'get').callsFake(async (opts) => {
if (opts.url === `https://graph.microsoft.com/v1.0/servicePrincipals/microsoft.graph.agentIdentityBlueprintPrincipal?$select=id,appDisplayName`) {
return {
value: limitedResponse
};
}

throw 'Invalid request';
});

await command.action(logger, { options: commandOptionsSchema.parse({ properties: 'id,appDisplayName' }) });

assert(
loggerLogSpy.calledWith(limitedResponse)
);
});

it('handles error when retrieving administrative units list failed', async () => {
sinon.stub(request, 'get').callsFake(async (opts) => {
if (opts.url === `https://graph.microsoft.com/v1.0/servicePrincipals/microsoft.graph.agentIdentityBlueprintPrincipal`) {
throw { error: { message: 'An error has occurred' } };
}
throw `Invalid request`;
});

await assert.rejects(
command.action(logger, { options: commandOptionsSchema.parse({}) }),
new CommandError('An error has occurred')
);
});
});
Loading
Loading