@knowttl/mg-axi 0.1.1 → 0.1.3
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 +251 -77
- package/dist/api.js +253 -8
- package/dist/bin/mg-axi-hook.js +31 -0
- package/dist/catalogue.js +693 -2
- package/dist/cli.js +155 -17
- package/dist/docs.js +175 -46
- package/dist/doctor.js +2 -2
- package/dist/entra-access-reviews.js +11 -4
- package/dist/entra-apps.js +171 -14
- package/dist/entra-audit-logs.js +101 -16
- package/dist/entra-auth-methods.js +8 -4
- package/dist/entra-certificate-auth.js +12 -8
- package/dist/entra-conditional-access.js +425 -15
- package/dist/entra-contacts.js +19 -12
- package/dist/entra-contracts.js +7 -4
- package/dist/entra-custom-security-attributes.js +19 -12
- package/dist/entra-data-policy-operations.js +7 -4
- package/dist/entra-delegated-admin.js +55 -6
- package/dist/entra-deleted-items.js +6 -4
- package/dist/entra-directory-objects.js +6 -4
- package/dist/entra-directory.js +19 -12
- package/dist/entra-domains.js +13 -8
- package/dist/entra-entitlement-management.js +12 -4
- package/dist/entra-federation-configurations.js +7 -4
- package/dist/entra-grants.js +8 -4
- package/dist/entra-group-lifecycle.js +13 -8
- package/dist/entra-group-pim.js +431 -0
- package/dist/entra-groups.js +13 -8
- package/dist/entra-identity-providers.js +7 -4
- package/dist/entra-lifecycle-workflows.js +152 -13
- package/dist/entra-multi-tenant-organization.js +7 -4
- package/dist/entra-on-premises-synchronization.js +6 -4
- package/dist/entra-organization.js +13 -8
- package/dist/entra-risk-prevention.js +442 -0
- package/dist/entra-risk.js +224 -9
- package/dist/entra-roles.js +204 -12
- package/dist/entra-subscriptions.js +6 -4
- package/dist/entra-terms-of-use.js +13 -8
- package/dist/entra-users.js +7 -4
- package/dist/graph-session.js +30 -5
- package/dist/hook.js +84 -0
- package/dist/list-totals.js +52 -0
- package/dist/setup.js +9 -1
- package/docs/coverage.md +743 -610
- package/inventory/operations.json +2 -2
- package/inventory/schema.json +1 -1
- package/package.json +4 -3
- package/skills/mg-axi/SKILL.md +86 -1
package/dist/api.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { AxiError } from "axi-sdk-js";
|
|
2
2
|
import { KNOWN_CONTACTED_REVIEWER_FIELDS, KNOWN_DECISION_FIELDS, KNOWN_DEFINITION_FIELDS, KNOWN_INSTANCE_FIELDS, KNOWN_STAGE_FIELDS } from "./entra-access-reviews.js";
|
|
3
3
|
import { KNOWN_ACCESS_PACKAGE_FIELDS, KNOWN_ASSIGNMENT_POLICY_FIELDS, KNOWN_CATALOG_FIELDS, KNOWN_RESOURCE_ROLE_SCOPE_FIELDS } from "./entra-entitlement-management.js";
|
|
4
|
-
import { KNOWN_LIFECYCLE_SETTINGS_FIELDS, KNOWN_RUN_FIELDS, KNOWN_SUBJECT_PROCESSING_FIELDS, KNOWN_TASK_DEFINITION_FIELDS, KNOWN_TASK_FIELDS, KNOWN_TASK_REPORT_FIELDS, KNOWN_USER_PROCESSING_FIELDS, KNOWN_WORKFLOW_FIELDS, KNOWN_WORKFLOW_TEMPLATE_FIELDS } from "./entra-lifecycle-workflows.js";
|
|
4
|
+
import { KNOWN_LIFECYCLE_SETTINGS_FIELDS, KNOWN_RUN_FIELDS, KNOWN_SUBJECT_PROCESSING_FIELDS, KNOWN_TASK_DEFINITION_FIELDS, KNOWN_TASK_FIELDS, KNOWN_TASK_PROCESSING_FIELDS, KNOWN_TASK_REPORT_FIELDS, KNOWN_USER_PROCESSING_FIELDS, KNOWN_WORKFLOW_FIELDS, KNOWN_WORKFLOW_TEMPLATE_FIELDS } from "./entra-lifecycle-workflows.js";
|
|
5
5
|
import { KNOWN_BRANDING_FIELDS, KNOWN_ORGANIZATION_FIELDS } from "./entra-organization.js";
|
|
6
6
|
import { KNOWN_CONTRACT_FIELDS } from "./entra-contracts.js";
|
|
7
7
|
import { KNOWN_DELEGATED_ADMIN_CUSTOMER_FIELDS, KNOWN_DELEGATED_ADMIN_RELATIONSHIP_FIELDS, KNOWN_DELEGATED_ADMIN_ACCESS_ASSIGNMENT_FIELDS, KNOWN_DELEGATED_ADMIN_OPERATION_FIELDS, KNOWN_DELEGATED_ADMIN_REQUEST_FIELDS } from "./entra-delegated-admin.js";
|
|
8
8
|
import { KNOWN_TENANT_INFORMATION_FIELDS } from "./entra-tenant-information.js";
|
|
9
9
|
import { KNOWN_MTO_FIELDS, KNOWN_MTO_JOIN_REQUEST_FIELDS, KNOWN_MTO_TENANT_FIELDS } from "./entra-multi-tenant-organization.js";
|
|
10
10
|
import { KNOWN_DATA_POLICY_FIELDS } from "./entra-data-policy-operations.js";
|
|
11
|
+
import { KNOWN_FRAUD_FIELDS, KNOWN_WAF_FIELDS, KNOWN_VERIFICATION_FIELDS } from "./entra-risk-prevention.js";
|
|
11
12
|
import { KNOWN_FEDERATION_FIELDS } from "./entra-federation-configurations.js";
|
|
12
13
|
import { KNOWN_CA_FIELDS, KNOWN_PKI_FIELDS } from "./entra-certificate-auth.js";
|
|
14
|
+
import { KNOWN_AUTH_CONTEXT_FIELDS, KNOWN_COMBO_FIELDS, KNOWN_DELETED_LOCATION_FIELDS, KNOWN_DELETED_POLICY_FIELDS, KNOWN_MODE_FIELDS, KNOWN_STRENGTH_FIELDS, KNOWN_TEMPLATE_FIELDS as KNOWN_CA_TEMPLATE_FIELDS } from "./entra-conditional-access.js";
|
|
13
15
|
import { KNOWN_SUBSCRIPTION_FIELDS } from "./entra-subscriptions.js";
|
|
16
|
+
import { KNOWN_TEMPLATE_FIELDS as KNOWN_ROLE_TEMPLATE_FIELDS, KNOWN_ROLE_MEMBER_FIELDS, KNOWN_SCOPED_MEMBER_FIELDS } from "./entra-roles.js";
|
|
17
|
+
import { KNOWN_ASSIGNMENT_INSTANCE_FIELDS, KNOWN_ASSIGNMENT_SCHEDULE_FIELDS, KNOWN_ELIGIBILITY_INSTANCE_FIELDS, KNOWN_ELIGIBILITY_REQUEST_FIELDS, KNOWN_ELIGIBILITY_SCHEDULE_FIELDS } from "./entra-group-pim.js";
|
|
14
18
|
import { KNOWN_SYNC_FIELDS } from "./entra-on-premises-synchronization.js";
|
|
15
19
|
import { KNOWN_ACCEPTANCE_FIELDS, KNOWN_AGREEMENT_FIELDS } from "./entra-terms-of-use.js";
|
|
16
20
|
import { KNOWN_DIRECTORY_OBJECT_FIELDS } from "./entra-directory-objects.js";
|
|
@@ -41,7 +45,7 @@ import { encodeGraphPathSegment, functionBindingFor, GraphSession, resolveSessio
|
|
|
41
45
|
// preview, /me and sensitive-area policy still runs inside the shared session,
|
|
42
46
|
// so raw reads cannot bypass named-command gating.
|
|
43
47
|
export const REVIEWED_ON = "2026-10-04";
|
|
44
|
-
const TRUNCATE_AT =
|
|
48
|
+
const TRUNCATE_AT = 500;
|
|
45
49
|
// Collections support server filtering, ordering and paging hints. Advanced
|
|
46
50
|
// queries ($search, $count=true) need per-endpoint ConsistencyLevel review and
|
|
47
51
|
// stay unsupported here; $skiptoken is server paging state, paged via --all.
|
|
@@ -57,12 +61,17 @@ const AUTH_METHOD_FIELDS = ["id", "createdDateTime", "displayName", "phoneNumber
|
|
|
57
61
|
const REGISTRATION_FIELDS = ["id", "userPrincipalName", "userDisplayName", "userType", "isAdmin", "isMfaRegistered", "isMfaCapable", "isPasswordlessCapable", "isSsprRegistered", "isSsprEnabled", "isSsprCapable", "userPreferredMethodForSecondaryAuthentication", "lastUpdatedDateTime"];
|
|
58
62
|
const SIGNIN_FIELDS = ["id", "createdDateTime", "userId", "userPrincipalName", "userDisplayName", "appDisplayName", "appId", "ipAddress", "location", "status", "conditionalAccessStatus", "riskDetail", "riskLevelAggregated", "riskLevelDuringSignIn", "riskState", "resourceDisplayName", "resourceId", "clientAppUsed"];
|
|
59
63
|
const AUDIT_FIELDS = ["id", "activityDateTime", "activityDisplayName", "category", "loggedByService", "operationType", "result", "resultReason", "correlationId", "initiatedBy", "targetResources"];
|
|
64
|
+
const PROVISIONING_FIELDS = ["id", "activityDateTime", "tenantId", "jobId", "cycleId", "changeId", "action", "durationInMilliseconds", "sourceSystem", "sourceIdentity", "targetSystem", "targetIdentity", "provisioningStatusInfo", "provisioningSteps", "modifiedProperties", "servicePrincipal", "initiatedBy"];
|
|
60
65
|
const RISKY_USER_FIELDS = ["id", "userPrincipalName", "userDisplayName", "riskDetail", "riskLastUpdatedDateTime", "riskLevel", "riskState"];
|
|
61
66
|
const RISK_DETECTION_FIELDS = ["id", "detectedDateTime", "activityDateTime", "userId", "userPrincipalName", "userDisplayName", "ipAddress", "location", "riskDetail", "riskLevel", "riskState", "riskEventType", "detectionTimingType", "lastUpdatedDateTime", "source"];
|
|
67
|
+
const RISKY_SP_FIELDS = ["id", "displayName", "appId", "servicePrincipalType", "riskDetail", "riskLastUpdatedDateTime", "riskLevel", "riskState", "isEnabled", "isProcessing"];
|
|
68
|
+
const RISKY_SP_HISTORY_FIELDS = ["id", "displayName", "appId", "servicePrincipalType", "servicePrincipalId", "riskDetail", "riskLastUpdatedDateTime", "riskLevel", "riskState", "isEnabled", "isProcessing", "initiatedBy", "activity"];
|
|
69
|
+
const SP_DETECTION_FIELDS = ["id", "detectedDateTime", "activityDateTime", "servicePrincipalId", "servicePrincipalDisplayName", "appId", "keyIds", "ipAddress", "location", "riskDetail", "riskLevel", "riskState", "riskEventType", "detectionTimingType", "lastUpdatedDateTime", "source", "additionalInfo"];
|
|
62
70
|
const APP_FIELDS = ["id", "appId", "displayName", "createdDateTime", "signInAudience", "publisherDomain", "keyCredentials", "passwordCredentials", "requiredResourceAccess", "web", "spa", "publicClient"];
|
|
63
71
|
const SP_FIELDS = ["id", "appId", "displayName", "servicePrincipalType", "accountEnabled", "appOwnerOrganizationId", "appRoleAssignmentRequired", "preferredSingleSignOnMode", "loginUrl"];
|
|
64
72
|
const GRANT_FIELDS = ["id", "clientId", "consentType", "principalId", "resourceId", "scope", "startTime", "expiryTime"];
|
|
65
73
|
const APP_ROLE_FIELDS = ["id", "appRoleId", "principalId", "principalDisplayName", "principalType", "resourceId", "resourceDisplayName", "createdDateTime"];
|
|
74
|
+
const FEDERATED_FIELDS = ["id", "name", "issuer", "subject", "description", "audiences"];
|
|
66
75
|
const ROLE_ASSIGNMENT_FIELDS = ["id", "principalId", "roleDefinitionId", "directoryScopeId", "appScopeId", "createdDateTime"];
|
|
67
76
|
const PIM_INSTANCE_FIELDS = ["id", "roleDefinitionId", "principalId", "assignmentType", "memberType", "startDateTime", "endDateTime", "activatedUsing"];
|
|
68
77
|
const DEVICE_FIELDS = ["id", "deviceId", "displayName", "operatingSystem", "operatingSystemVersion", "trustType", "isCompliant", "isManaged", "accountEnabled", "createdDateTime", "approximateLastSignInDateTime", "manufacturer", "model"];
|
|
@@ -104,6 +113,62 @@ export const REVIEWED_ROUTES = [
|
|
|
104
113
|
{ id: "v1.0:GET:/identity/conditionalAccess/namedLocations/{namedLocation-id}", kind: "single", query: SINGLE_QUERY, fields: NAMED_LOCATION_FIELDS,
|
|
105
114
|
access: "D/A Policy.Read.All. Delegated callers pass it as --scopes; a supported administrator role (for example Security Reader) is also required.",
|
|
106
115
|
sources: ["https://learn.microsoft.com/graph/api/countrynamedlocation-get?view=graph-rest-1.0"] },
|
|
116
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationStrength/policies", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_STRENGTH_FIELDS,
|
|
117
|
+
access: "D/A Policy.Read.AuthenticationMethod. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
118
|
+
note: "Conditional Access needs P1.",
|
|
119
|
+
sources: ["https://learn.microsoft.com/en-us/graph/api/authenticationstrengthroot-list-policies?view=graph-rest-1.0"] },
|
|
120
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationStrength/policies/{authenticationStrengthPolicy-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_STRENGTH_FIELDS,
|
|
121
|
+
access: "D/A Policy.Read.AuthenticationMethod. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
122
|
+
note: "Conditional Access needs P1.",
|
|
123
|
+
sources: ["https://learn.microsoft.com/en-us/graph/api/authenticationstrengthpolicy-get?view=graph-rest-1.0"] },
|
|
124
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationStrength/policies/{authenticationStrengthPolicy-id}/combinationConfigurations", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_COMBO_FIELDS, keepODataType: true,
|
|
125
|
+
access: "D/A Policy.Read.AuthenticationMethod. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
126
|
+
note: "Conditional Access needs P1. Rows are polymorphic: the @odata.type discriminator rides along automatically to name the configuration kind.",
|
|
127
|
+
sources: ["https://learn.microsoft.com/graph/api/authenticationstrengthpolicy-list-combinationconfigurations?view=graph-rest-1.0"] },
|
|
128
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationStrength/policies/{authenticationStrengthPolicy-id}/combinationConfigurations/{authenticationCombinationConfiguration-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_COMBO_FIELDS, keepODataType: true,
|
|
129
|
+
access: "D/A Policy.Read.AuthenticationMethod. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
130
|
+
note: "Conditional Access needs P1. Rows are polymorphic: the @odata.type discriminator rides along automatically to name the configuration kind.",
|
|
131
|
+
sources: ["https://learn.microsoft.com/graph/api/authenticationcombinationconfiguration-get?view=graph-rest-1.0"] },
|
|
132
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationStrength/authenticationMethodModes", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_MODE_FIELDS,
|
|
133
|
+
access: "D/A Policy.Read.AuthenticationMethod. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
134
|
+
note: "Conditional Access needs P1.",
|
|
135
|
+
sources: ["https://learn.microsoft.com/graph/api/authenticationstrengthroot-list-authenticationmethodmodes?view=graph-rest-1.0"] },
|
|
136
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationStrength/authenticationMethodModes/{authenticationMethodModeDetail-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_MODE_FIELDS,
|
|
137
|
+
access: "D/A Policy.Read.AuthenticationMethod. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
138
|
+
note: "Conditional Access needs P1.",
|
|
139
|
+
sources: ["https://learn.microsoft.com/en-us/graph/api/authenticationmethodmodedetail-get?view=graph-rest-1.0"] },
|
|
140
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/templates", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_CA_TEMPLATE_FIELDS,
|
|
141
|
+
access: "D/A Policy.Read.All. Delegated callers pass it as --scopes; a supported administrator role (for example Security Reader) is also required.",
|
|
142
|
+
note: "Conditional Access needs P1.",
|
|
143
|
+
sources: ["https://learn.microsoft.com/en-us/graph/api/conditionalaccessroot-list-templates?view=graph-rest-1.0"] },
|
|
144
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/templates/{conditionalAccessTemplate-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_CA_TEMPLATE_FIELDS,
|
|
145
|
+
access: "D/A Policy.Read.All. Delegated callers pass it as --scopes; a supported administrator role (for example Security Reader) is also required.",
|
|
146
|
+
note: "Conditional Access needs P1.",
|
|
147
|
+
sources: ["https://learn.microsoft.com/en-us/graph/api/conditionalaccesstemplate-get?view=graph-rest-1.0"] },
|
|
148
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationContextClassReferences", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_AUTH_CONTEXT_FIELDS,
|
|
149
|
+
access: "D/A AuthenticationContext.Read.All. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Global Reader, Global Secure Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
150
|
+
note: "Conditional Access needs P1.",
|
|
151
|
+
sources: ["https://learn.microsoft.com/graph/api/conditionalaccessroot-list-authenticationcontextclassreferences?view=graph-rest-1.0"] },
|
|
152
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/authenticationContextClassReferences/{authenticationContextClassReference-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_AUTH_CONTEXT_FIELDS,
|
|
153
|
+
access: "D/A AuthenticationContext.Read.All. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Global Reader, Global Secure Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
154
|
+
note: "The get page documents no optional query parameters; $select travels as the standard single-object projection. Conditional Access needs P1.",
|
|
155
|
+
sources: ["https://learn.microsoft.com/graph/api/authenticationcontextclassreference-get?view=graph-rest-1.0"] },
|
|
156
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/deletedItems/policies", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_DELETED_POLICY_FIELDS,
|
|
157
|
+
access: "D/A Policy.Read.All. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Global Reader, Global Secure Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
158
|
+
note: "No v1.0 operation-level documentation page; access follows the beta policyDeletableItem contract for conditional-access objects with the conditionalAccessPolicy resource reference. Soft-deleted policies restore within 30 days; restore is beta-only and out of scope. Conditional Access needs P1.",
|
|
159
|
+
sources: ["https://learn.microsoft.com/en-us/graph/api/policydeletableitem-list?view=graph-rest-beta", "https://learn.microsoft.com/en-us/graph/api/resources/policydeletableitem?view=graph-rest-beta"] },
|
|
160
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/deletedItems/policies/{conditionalAccessPolicy-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_DELETED_POLICY_FIELDS,
|
|
161
|
+
access: "D/A Policy.Read.All. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Global Reader, Global Secure Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
162
|
+
note: "No v1.0 operation-level documentation page; access follows the beta policyDeletableItem contract for conditional-access objects with the conditionalAccessPolicy resource reference. Soft-deleted policies restore within 30 days; restore is beta-only and out of scope. Conditional Access needs P1.",
|
|
163
|
+
sources: ["https://learn.microsoft.com/en-us/graph/api/policydeletableitem-get?view=graph-rest-beta", "https://learn.microsoft.com/en-us/graph/api/resources/policydeletableitem?view=graph-rest-beta"] },
|
|
164
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/deletedItems/namedLocations", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_DELETED_LOCATION_FIELDS, keepODataType: true,
|
|
165
|
+
access: "D/A Policy.Read.All. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Global Reader, Global Secure Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
166
|
+
note: "No v1.0 operation-level documentation page; access follows the beta policyDeletableItem contract for conditional-access objects with the namedLocation resource reference. Rows are polymorphic: the @odata.type discriminator rides along automatically to name the location kind. Soft-deleted locations restore within 30 days; restore is beta-only and out of scope. Conditional Access needs P1.",
|
|
167
|
+
sources: ["https://learn.microsoft.com/en-us/graph/api/policydeletableitem-list?view=graph-rest-beta", "https://learn.microsoft.com/en-us/graph/api/resources/policydeletableitem?view=graph-rest-beta"] },
|
|
168
|
+
{ id: "v1.0:GET:/identity/conditionalAccess/deletedItems/namedLocations/{namedLocation-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_DELETED_LOCATION_FIELDS, keepODataType: true,
|
|
169
|
+
access: "D/A Policy.Read.All. Delegated callers pass it as --scopes; a supported administrator role (Conditional Access Administrator, Global Reader, Global Secure Access Administrator, Security Administrator or Security Reader) is also required.",
|
|
170
|
+
note: "No v1.0 operation-level documentation page; access follows the beta policyDeletableItem contract for conditional-access objects with the namedLocation resource reference. Soft-deleted locations restore within 30 days; restore is beta-only and out of scope. Conditional Access needs P1.",
|
|
171
|
+
sources: ["https://learn.microsoft.com/en-us/graph/api/policydeletableitem-get?view=graph-rest-beta", "https://learn.microsoft.com/en-us/graph/api/resources/policydeletableitem?view=graph-rest-beta"] },
|
|
107
172
|
{ id: "v1.0:GET:/users/{user-id}/authentication/methods", kind: "collection", query: ["$select"], fields: AUTH_METHOD_FIELDS,
|
|
108
173
|
access: "D/A UserAuthenticationMethod.Read.All for other users; delegated self UserAuthenticationMethod.Read. Dedicated administrator roles also apply.",
|
|
109
174
|
note: "Targeted per-user inspection only; aggregate coverage belongs to the registration report, never to a scan across users.",
|
|
@@ -122,6 +187,10 @@ export const REVIEWED_ROUTES = [
|
|
|
122
187
|
{ id: "v1.0:GET:/auditLogs/directoryAudits", kind: "collection", query: COLLECTION_QUERY, fields: AUDIT_FIELDS,
|
|
123
188
|
access: "D/A AuditLog.Read.All. Delegated callers pass it as --scopes.",
|
|
124
189
|
sources: ["https://learn.microsoft.com/graph/api/directoryaudit-list?view=graph-rest-1.0"] },
|
|
190
|
+
{ id: "v1.0:GET:/auditLogs/provisioning", kind: "collection", query: COLLECTION_QUERY, fields: PROVISIONING_FIELDS,
|
|
191
|
+
access: "D/A AuditLog.Read.All and Directory.Read.All. Delegated callers pass both as --scopes; Reports Reader is the least privileged directory role.",
|
|
192
|
+
note: "Entra ID P1/P2 licence prerequisite; retention is 30 days on premium and 7 days on free.",
|
|
193
|
+
sources: ["https://learn.microsoft.com/graph/api/provisioningobjectsummary-list?view=graph-rest-1.0"] },
|
|
125
194
|
{ id: "v1.0:GET:/identityProtection/riskyUsers", kind: "collection", query: COLLECTION_QUERY, fields: RISKY_USER_FIELDS,
|
|
126
195
|
access: "D/A IdentityRiskyUser.Read.All. Delegated callers pass it as --scopes.",
|
|
127
196
|
note: "Full investigation needs P2/Suite; limited results stay limited, never reinterpreted as empty.",
|
|
@@ -136,6 +205,28 @@ export const REVIEWED_ROUTES = [
|
|
|
136
205
|
{ id: "v1.0:GET:/identityProtection/riskDetections/{riskDetection-id}", kind: "single", query: SINGLE_QUERY, fields: RISK_DETECTION_FIELDS,
|
|
137
206
|
access: "D/A IdentityRiskEvent.Read.All. Delegated callers pass it as --scopes.",
|
|
138
207
|
sources: ["https://learn.microsoft.com/graph/api/riskdetection-get?view=graph-rest-1.0"] },
|
|
208
|
+
{ id: "v1.0:GET:/identityProtection/riskyServicePrincipals", kind: "collection", query: COLLECTION_QUERY, fields: RISKY_SP_FIELDS,
|
|
209
|
+
access: "D/A IdentityRiskyServicePrincipal.Read.All. Delegated callers pass it as --scopes.",
|
|
210
|
+
note: "The riskyServicePrincipals API requires a Microsoft Entra Workload Identities Premium licence; limited results stay limited, never reinterpreted as empty.",
|
|
211
|
+
sources: ["https://learn.microsoft.com/graph/api/identityprotectionroot-list-riskyserviceprincipals?view=graph-rest-1.0"] },
|
|
212
|
+
{ id: "v1.0:GET:/identityProtection/riskyServicePrincipals/{riskyServicePrincipal-id}", kind: "single", query: SINGLE_QUERY, fields: RISKY_SP_FIELDS,
|
|
213
|
+
access: "D/A IdentityRiskyServicePrincipal.Read.All. Delegated callers pass it as --scopes.",
|
|
214
|
+
sources: ["https://learn.microsoft.com/graph/api/riskyserviceprincipal-get?view=graph-rest-1.0"] },
|
|
215
|
+
{ id: "v1.0:GET:/identityProtection/riskyServicePrincipals/{riskyServicePrincipal-id}/history", kind: "collection", query: COLLECTION_QUERY, fields: RISKY_SP_HISTORY_FIELDS,
|
|
216
|
+
access: "D/A IdentityRiskyServicePrincipal.Read.All. Delegated callers pass it as --scopes.",
|
|
217
|
+
note: "Per-principal risk history; history items inherit the principal properties and add the service-principal identifier with the actor/activity of the change.",
|
|
218
|
+
sources: ["https://learn.microsoft.com/graph/api/riskyserviceprincipal-list-history?view=graph-rest-1.0"] },
|
|
219
|
+
{ id: "v1.0:GET:/identityProtection/riskyServicePrincipals/{riskyServicePrincipal-id}/history/{riskyServicePrincipalHistoryItem-id}", kind: "single", query: SINGLE_QUERY, fields: RISKY_SP_HISTORY_FIELDS,
|
|
220
|
+
access: "D/A IdentityRiskyServicePrincipal.Read.All. Delegated callers pass it as --scopes.",
|
|
221
|
+
note: "No operation-level documentation page; access follows the parent history-list contract and the history-item resource reference.",
|
|
222
|
+
sources: ["https://learn.microsoft.com/graph/api/riskyserviceprincipal-list-history?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/riskyserviceprincipalhistoryitem?view=graph-rest-1.0"] },
|
|
223
|
+
{ id: "v1.0:GET:/identityProtection/servicePrincipalRiskDetections", kind: "collection", query: COLLECTION_QUERY, fields: SP_DETECTION_FIELDS,
|
|
224
|
+
access: "D/A IdentityRiskEvent.Read.All. Delegated callers pass it as --scopes.",
|
|
225
|
+
note: "The servicePrincipalRiskDetection API requires a Microsoft Entra Workload Identities Premium licence; riskDetail and riskLevel report hidden without it.",
|
|
226
|
+
sources: ["https://learn.microsoft.com/graph/api/identityprotectionroot-list-serviceprincipalriskdetections?view=graph-rest-1.0"] },
|
|
227
|
+
{ id: "v1.0:GET:/identityProtection/servicePrincipalRiskDetections/{servicePrincipalRiskDetection-id}", kind: "single", query: SINGLE_QUERY, fields: SP_DETECTION_FIELDS,
|
|
228
|
+
access: "D/A IdentityRiskEvent.Read.All. Delegated callers pass it as --scopes.",
|
|
229
|
+
sources: ["https://learn.microsoft.com/graph/api/serviceprincipalriskdetection-get?view=graph-rest-1.0"] },
|
|
139
230
|
{ id: "v1.0:GET:/applications", kind: "collection", query: COLLECTION_QUERY, fields: APP_FIELDS,
|
|
140
231
|
access: "D/A Application.Read.All. Delegated callers pass it as --scopes.",
|
|
141
232
|
note: "appId (client ID) is distinct from the object id. Credential fields carry expiry metadata only; GET never returns secret values and success redaction still applies.",
|
|
@@ -156,6 +247,34 @@ export const REVIEWED_ROUTES = [
|
|
|
156
247
|
access: "D/A Application.Read.All. Delegated callers pass it as --scopes.",
|
|
157
248
|
note: "Actual granted assignments; requested permissions are a separate contract.",
|
|
158
249
|
sources: ["https://learn.microsoft.com/graph/api/serviceprincipal-list-approleassignments?view=graph-rest-1.0"] },
|
|
250
|
+
{ id: "v1.0:GET:/servicePrincipals/{servicePrincipal-id}/appRoleAssignments/{appRoleAssignment-id}", kind: "single", query: SINGLE_QUERY, fields: APP_ROLE_FIELDS,
|
|
251
|
+
access: "D/A Application.Read.All. Delegated callers pass it as --scopes.",
|
|
252
|
+
note: "One granted assignment on the client service principal; requested permissions are a separate contract.",
|
|
253
|
+
sources: ["https://learn.microsoft.com/graph/api/approleassignment-get?view=graph-rest-1.0"] },
|
|
254
|
+
{ id: "v1.0:GET:/servicePrincipals/{servicePrincipal-id}/appRoleAssignedTo", kind: "collection", query: COLLECTION_QUERY, fields: APP_ROLE_FIELDS,
|
|
255
|
+
access: "D/A Application.Read.All. Delegated callers pass it as --scopes.",
|
|
256
|
+
note: "Principals assigned to this resource service principal; the reverse view of appRoleAssignments.",
|
|
257
|
+
sources: ["https://learn.microsoft.com/graph/api/serviceprincipal-list-approleassignedto?view=graph-rest-1.0"] },
|
|
258
|
+
{ id: "v1.0:GET:/servicePrincipals/{servicePrincipal-id}/appRoleAssignedTo/{appRoleAssignment-id}", kind: "single", query: SINGLE_QUERY, fields: APP_ROLE_FIELDS,
|
|
259
|
+
access: "D/A Application.Read.All. Delegated callers pass it as --scopes.",
|
|
260
|
+
note: "One principal assignment on the resource service principal; the reverse view of appRoleAssignments.",
|
|
261
|
+
sources: ["https://learn.microsoft.com/graph/api/approleassignment-get?view=graph-rest-1.0"] },
|
|
262
|
+
{ id: "v1.0:GET:/applications/{application-id}/federatedIdentityCredentials", kind: "collection", query: COLLECTION_QUERY, fields: FEDERATED_FIELDS,
|
|
263
|
+
access: "D/A Application.Read.All. Delegated callers pass it as --scopes.",
|
|
264
|
+
note: "Workload-identity trust metadata only; GET never returns secret values and success redaction still applies.",
|
|
265
|
+
sources: ["https://learn.microsoft.com/graph/api/federatedidentitycredential-list?view=graph-rest-1.0"] },
|
|
266
|
+
{ id: "v1.0:GET:/applications/{application-id}/federatedIdentityCredentials/{federatedIdentityCredential-id}", kind: "single", query: SINGLE_QUERY, fields: FEDERATED_FIELDS,
|
|
267
|
+
access: "D/A Application.Read.All. Delegated callers pass it as --scopes.",
|
|
268
|
+
note: "One workload-identity trust entry; metadata only, never secret values.",
|
|
269
|
+
sources: ["https://learn.microsoft.com/graph/api/federatedidentitycredential-get?view=graph-rest-1.0"] },
|
|
270
|
+
{ id: "v1.0:GET:/servicePrincipals/{servicePrincipal-id}/federatedIdentityCredentials", kind: "collection", query: COLLECTION_QUERY, fields: FEDERATED_FIELDS,
|
|
271
|
+
access: "D/A Application.Read.All. Delegated callers pass it as --scopes.",
|
|
272
|
+
note: "Same federatedIdentityCredential resource contract as the application navigation; metadata only, never secret values.",
|
|
273
|
+
sources: ["https://learn.microsoft.com/graph/api/federatedidentitycredential-list?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/federatedidentitycredential?view=graph-rest-1.0"] },
|
|
274
|
+
{ id: "v1.0:GET:/servicePrincipals/{servicePrincipal-id}/federatedIdentityCredentials/{federatedIdentityCredential-id}", kind: "single", query: SINGLE_QUERY, fields: FEDERATED_FIELDS,
|
|
275
|
+
access: "D/A Application.Read.All. Delegated callers pass it as --scopes.",
|
|
276
|
+
note: "Same federatedIdentityCredential resource contract as the application navigation; metadata only, never secret values.",
|
|
277
|
+
sources: ["https://learn.microsoft.com/graph/api/federatedidentitycredential-get?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/federatedidentitycredential?view=graph-rest-1.0"] },
|
|
159
278
|
{ id: "v1.0:GET:/oauth2PermissionGrants", kind: "collection", query: COLLECTION_QUERY, fields: GRANT_FIELDS,
|
|
160
279
|
access: "D/A Directory.Read.All as the read choice. Delegated callers pass it as --scopes.",
|
|
161
280
|
note: "Actual granted consent; requested permissions are a separate contract.",
|
|
@@ -175,6 +294,73 @@ export const REVIEWED_ROUTES = [
|
|
|
175
294
|
access: "D/A RoleAssignmentSchedule.Read.Directory. Delegated callers pass it as --scopes.",
|
|
176
295
|
note: "Active (including activated eligible) assignments; PIM needs P2 or ID Governance.",
|
|
177
296
|
sources: ["https://learn.microsoft.com/graph/api/rbacapplication-list-roleassignmentscheduleinstances?view=graph-rest-1.0"] },
|
|
297
|
+
{ id: "v1.0:GET:/directoryRoleTemplates", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_ROLE_TEMPLATE_FIELDS,
|
|
298
|
+
access: "D/A RoleManagement.Read.Directory. Delegated callers pass it as --scopes.",
|
|
299
|
+
note: "Templates describe every role; activation state lives on directoryRoles.",
|
|
300
|
+
sources: ["https://learn.microsoft.com/graph/api/directoryroletemplate-list?view=graph-rest-1.0"] },
|
|
301
|
+
{ id: "v1.0:GET:/directoryRoleTemplates/{directoryRoleTemplate-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_ROLE_TEMPLATE_FIELDS,
|
|
302
|
+
access: "D/A RoleManagement.Read.Directory. Delegated callers pass it as --scopes.",
|
|
303
|
+
sources: ["https://learn.microsoft.com/graph/api/directoryroletemplate-get?view=graph-rest-1.0"] },
|
|
304
|
+
{ id: "v1.0:GET:/directoryRoles/{directoryRole-id}/members", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_ROLE_MEMBER_FIELDS,
|
|
305
|
+
access: "D/A RoleManagement.Read.Directory. Delegated callers pass it as --scopes.",
|
|
306
|
+
note: "Members are the assigned principals; @odata.type names each member kind.",
|
|
307
|
+
sources: ["https://learn.microsoft.com/graph/api/directoryrole-list-members?view=graph-rest-1.0"] },
|
|
308
|
+
{ id: "v1.0:GET:/directoryRoles/{directoryRole-id}/scopedMembers", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_SCOPED_MEMBER_FIELDS,
|
|
309
|
+
access: "D/A RoleManagement.Read.Directory. Delegated callers pass it as --scopes.",
|
|
310
|
+
note: "Scoped members bind one role to one principal within one directory scope; administrative-unit scopes need P1.",
|
|
311
|
+
sources: ["https://learn.microsoft.com/graph/api/directoryrole-list-scopedmembers?view=graph-rest-1.0"] },
|
|
312
|
+
{ id: "v1.0:GET:/directoryRoles/{directoryRole-id}/scopedMembers/{scopedRoleMembership-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_SCOPED_MEMBER_FIELDS,
|
|
313
|
+
access: "D/A RoleManagement.Read.Directory. Delegated callers pass it as --scopes.",
|
|
314
|
+
note: "Administrative-unit scopes need P1.",
|
|
315
|
+
sources: ["https://learn.microsoft.com/graph/api/scopedrolemembership-get?view=graph-rest-1.0"] },
|
|
316
|
+
{ id: "v1.0:GET:/scopedRoleMemberships", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_SCOPED_MEMBER_FIELDS,
|
|
317
|
+
access: "D/A RoleManagement.Read.Directory. Delegated callers pass it as --scopes.",
|
|
318
|
+
note: "Administrative-unit-scoped admin assignments; directory-wide assignments live on roleAssignments. Administrative-unit scopes need P1.",
|
|
319
|
+
sources: ["https://learn.microsoft.com/graph/api/scopedrolemembership-list?view=graph-rest-1.0"] },
|
|
320
|
+
{ id: "v1.0:GET:/scopedRoleMemberships/{scopedRoleMembership-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_SCOPED_MEMBER_FIELDS,
|
|
321
|
+
access: "D/A RoleManagement.Read.Directory. Delegated callers pass it as --scopes.",
|
|
322
|
+
note: "Administrative-unit scopes need P1.",
|
|
323
|
+
sources: ["https://learn.microsoft.com/graph/api/scopedrolemembership-get?view=graph-rest-1.0"] },
|
|
324
|
+
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/assignmentSchedules", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_ASSIGNMENT_SCHEDULE_FIELDS,
|
|
325
|
+
access: "D/A PrivilegedAssignmentSchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
326
|
+
note: "Assignment schedules govern group membership or ownership over time; PIM for Groups needs P2 or ID Governance; lists require $filter on groupId or principalId. AssignmentScheduleRequests stay out: their least privilege is the write scope PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup.",
|
|
327
|
+
sources: ["https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-assignmentschedules?view=graph-rest-1.0"] },
|
|
328
|
+
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/assignmentSchedules/{privilegedAccessGroupAssignmentSchedule-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_ASSIGNMENT_SCHEDULE_FIELDS,
|
|
329
|
+
access: "D/A PrivilegedAssignmentSchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
330
|
+
note: "PIM for Groups needs P2 or ID Governance.",
|
|
331
|
+
sources: ["https://learn.microsoft.com/graph/api/privilegedaccessgroupassignmentschedule-get?view=graph-rest-1.0"] },
|
|
332
|
+
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/assignmentScheduleInstances", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_ASSIGNMENT_INSTANCE_FIELDS,
|
|
333
|
+
access: "D/A PrivilegedAssignmentSchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
334
|
+
note: "Provisioned assignment windows; PIM for Groups needs P2 or ID Governance; lists require $filter on groupId or principalId.",
|
|
335
|
+
sources: ["https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-assignmentscheduleinstances?view=graph-rest-1.0"] },
|
|
336
|
+
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/assignmentScheduleInstances/{privilegedAccessGroupAssignmentScheduleInstance-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_ASSIGNMENT_INSTANCE_FIELDS,
|
|
337
|
+
access: "D/A PrivilegedAssignmentSchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
338
|
+
note: "PIM for Groups needs P2 or ID Governance.",
|
|
339
|
+
sources: ["https://learn.microsoft.com/graph/api/privilegedaccessgroupassignmentscheduleinstance-get?view=graph-rest-1.0"] },
|
|
340
|
+
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/eligibilitySchedules", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_ELIGIBILITY_SCHEDULE_FIELDS,
|
|
341
|
+
access: "D/A PrivilegedEligibilitySchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
342
|
+
note: "Eligibility schedules govern who may activate; PIM for Groups needs P2 or ID Governance; lists require $filter on groupId or principalId.",
|
|
343
|
+
sources: ["https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-eligibilityschedules?view=graph-rest-1.0"] },
|
|
344
|
+
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/eligibilitySchedules/{privilegedAccessGroupEligibilitySchedule-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_ELIGIBILITY_SCHEDULE_FIELDS,
|
|
345
|
+
access: "D/A PrivilegedEligibilitySchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
346
|
+
note: "PIM for Groups needs P2 or ID Governance.",
|
|
347
|
+
sources: ["https://learn.microsoft.com/graph/api/privilegedaccessgroupeligibilityschedule-get?view=graph-rest-1.0"] },
|
|
348
|
+
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/eligibilityScheduleInstances", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_ELIGIBILITY_INSTANCE_FIELDS,
|
|
349
|
+
access: "D/A PrivilegedEligibilitySchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
350
|
+
note: "Provisioned eligibility windows; PIM for Groups needs P2 or ID Governance; lists require $filter on groupId or principalId.",
|
|
351
|
+
sources: ["https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-eligibilityscheduleinstances?view=graph-rest-1.0"] },
|
|
352
|
+
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/eligibilityScheduleInstances/{privilegedAccessGroupEligibilityScheduleInstance-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_ELIGIBILITY_INSTANCE_FIELDS,
|
|
353
|
+
access: "D/A PrivilegedEligibilitySchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
354
|
+
note: "PIM for Groups needs P2 or ID Governance.",
|
|
355
|
+
sources: ["https://learn.microsoft.com/graph/api/privilegedaccessgroupeligibilityscheduleinstance-get?view=graph-rest-1.0"] },
|
|
356
|
+
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/eligibilityScheduleRequests", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_ELIGIBILITY_REQUEST_FIELDS,
|
|
357
|
+
access: "D/A PrivilegedEligibilitySchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
358
|
+
note: "Eligibility asks plus outcomes; justification text rides only behind an explicit $select; PIM for Groups needs P2 or ID Governance; lists require $filter on groupId or principalId.",
|
|
359
|
+
sources: ["https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-eligibilityschedulerequests?view=graph-rest-1.0"] },
|
|
360
|
+
{ id: "v1.0:GET:/identityGovernance/privilegedAccess/group/eligibilityScheduleRequests/{privilegedAccessGroupEligibilityScheduleRequest-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_ELIGIBILITY_REQUEST_FIELDS,
|
|
361
|
+
access: "D/A PrivilegedEligibilitySchedule.Read.AzureADGroup. Delegated callers pass it as --scopes.",
|
|
362
|
+
note: "PIM for Groups needs P2 or ID Governance.",
|
|
363
|
+
sources: ["https://learn.microsoft.com/graph/api/privilegedaccessgroupeligibilityschedulerequest-get?view=graph-rest-1.0"] },
|
|
178
364
|
{ id: "v1.0:GET:/devices", kind: "collection", query: COLLECTION_QUERY, fields: DEVICE_FIELDS,
|
|
179
365
|
access: "D/A Device.Read.All. Delegated callers pass it as --scopes.",
|
|
180
366
|
note: "Directory-device scope only; Intune device management is a separately authorized surface.",
|
|
@@ -551,6 +737,41 @@ export const REVIEWED_ROUTES = [
|
|
|
551
737
|
access: "D/A User.Export.All plus User.Read.All. Delegated callers pass both as --scopes; delegated access additionally needs Company Administrator, the privileged role documented for export reads; personal Microsoft accounts are not supported. No P1/P2 prerequisite is stated for this read.",
|
|
552
738
|
note: "storageLocation always renders as the redaction marker: export blob URLs and signed links never reach output. Workforce context only; export submission belongs to no read slice.",
|
|
553
739
|
sources: ["https://learn.microsoft.com/graph/api/datapolicyoperation-get?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/datapolicyoperation?view=graph-rest-1.0"] },
|
|
740
|
+
{ id: "v1.0:GET:/identity/riskPrevention/fraudProtectionProviders", kind: "collection", query: ["$select"], fields: KNOWN_FRAUD_FIELDS, keepODataType: true,
|
|
741
|
+
access: "D RiskPreventionProviders.Read.All (RiskPreventionProviders.ReadWrite.All is the documented higher-privileged alternative). Delegated callers pass it as --scopes; delegated access additionally needs a directory role that can read risk-prevention configuration (Security Reader is the least-privileged read-only role); personal Microsoft accounts are not supported and Graph documents no supported application permission, so application profiles are refused before credentials. No P1/P2 prerequisite is stated for these reads.",
|
|
742
|
+
delegatedOnly: true,
|
|
743
|
+
note: "Graph documents $select only on the fraud-protection-provider list; $filter is not reviewed here. Arkose privateKey/publicKey and HUMAN serverToken are never projected: the first two are key material and the server token authenticates HUMAN API calls. Workforce context only; external-customer user flows and provisioning stay scheduled.",
|
|
744
|
+
sources: ["https://learn.microsoft.com/graph/api/riskpreventioncontainer-list-fraudprotectionproviders?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/fraudprotectionprovider?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/arkosefraudprotectionprovider?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/humansecurityfraudprotectionprovider?view=graph-rest-1.0"] },
|
|
745
|
+
{ id: "v1.0:GET:/identity/riskPrevention/fraudProtectionProviders/{fraudProtectionProvider-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_FRAUD_FIELDS, keepODataType: true,
|
|
746
|
+
access: "D RiskPreventionProviders.Read.All (RiskPreventionProviders.ReadWrite.All is the documented higher-privileged alternative). Delegated callers pass it as --scopes; delegated access additionally needs a directory role that can read risk-prevention configuration (Security Reader is the least-privileged read-only role); personal Microsoft accounts are not supported and Graph documents no supported application permission, so application profiles are refused before credentials. No P1/P2 prerequisite is stated for this read.",
|
|
747
|
+
delegatedOnly: true,
|
|
748
|
+
note: "Arkose privateKey/publicKey and HUMAN serverToken are never projected: the first two are key material and the server token authenticates HUMAN API calls. Workforce context only; external-customer user flows and provisioning stay scheduled.",
|
|
749
|
+
sources: ["https://learn.microsoft.com/graph/api/fraudprotectionprovider-get?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/fraudprotectionprovider?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/arkosefraudprotectionprovider?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/humansecurityfraudprotectionprovider?view=graph-rest-1.0"] },
|
|
750
|
+
{ id: "v1.0:GET:/identity/riskPrevention/webApplicationFirewallProviders", kind: "collection", query: ["$select", "$filter"], fields: KNOWN_WAF_FIELDS, keepODataType: true,
|
|
751
|
+
access: "D RiskPreventionProviders.Read.All (RiskPreventionProviders.ReadWrite.All is the documented higher-privileged alternative). Delegated callers pass it as --scopes; delegated access additionally needs a directory role that can read risk-prevention configuration (Security Reader is the least-privileged read-only role); personal Microsoft accounts are not supported and Graph documents no supported application permission, so application profiles are refused before credentials. No P1/P2 prerequisite is stated for these reads.",
|
|
752
|
+
delegatedOnly: true,
|
|
753
|
+
note: "Filtering passes through as plain $filter with no $count or ConsistencyLevel contract. Akamai clientSecret/clientToken/accessToken and Cloudflare apiToken are never projected: all four authenticate provider APIs. Workforce context only; verification submission and external-customer user flows stay scheduled.",
|
|
754
|
+
sources: ["https://learn.microsoft.com/graph/api/riskpreventioncontainer-list-webapplicationfirewallproviders?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/webapplicationfirewallprovider?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/akamaiwebapplicationfirewallprovider?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/cloudflarewebapplicationfirewallprovider?view=graph-rest-1.0"] },
|
|
755
|
+
{ id: "v1.0:GET:/identity/riskPrevention/webApplicationFirewallProviders/{webApplicationFirewallProvider-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_WAF_FIELDS, keepODataType: true,
|
|
756
|
+
access: "D RiskPreventionProviders.Read.All (RiskPreventionProviders.ReadWrite.All is the documented higher-privileged alternative). Delegated callers pass it as --scopes; delegated access additionally needs a directory role that can read risk-prevention configuration (Security Reader is the least-privileged read-only role); personal Microsoft accounts are not supported and Graph documents no supported application permission, so application profiles are refused before credentials. No P1/P2 prerequisite is stated for this read.",
|
|
757
|
+
delegatedOnly: true,
|
|
758
|
+
note: "Akamai clientSecret/clientToken/accessToken and Cloudflare apiToken are never projected: all four authenticate provider APIs. Workforce context only; verification submission and external-customer user flows stay scheduled.",
|
|
759
|
+
sources: ["https://learn.microsoft.com/graph/api/webapplicationfirewallprovider-get?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/webapplicationfirewallprovider?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/akamaiwebapplicationfirewallprovider?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/cloudflarewebapplicationfirewallprovider?view=graph-rest-1.0"] },
|
|
760
|
+
{ id: "v1.0:GET:/identity/riskPrevention/webApplicationFirewallVerifications", kind: "collection", query: ["$select", "$filter"], fields: KNOWN_VERIFICATION_FIELDS,
|
|
761
|
+
access: "D RiskPreventionProviders.Read.All. Delegated callers pass it as --scopes; delegated access additionally needs a directory role that can read risk-prevention configuration (Security Reader is the least-privileged read-only role); personal Microsoft accounts are not supported and Graph documents no supported application permission, so application profiles are refused before credentials. No P1/P2 prerequisite is stated for these reads.",
|
|
762
|
+
delegatedOnly: true,
|
|
763
|
+
note: "Filtering passes through as plain $filter with no $count or ConsistencyLevel contract ($expand stays unreviewed). verificationResult and verifiedDetails ride whole as complex objects. Rows never carry provider detail: the provider navigation has its own sub-read. Workforce context only; verification submission stays scheduled.",
|
|
764
|
+
sources: ["https://learn.microsoft.com/graph/api/riskpreventioncontainer-list-webapplicationfirewallverifications?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/webapplicationfirewallverificationmodel?view=graph-rest-1.0"] },
|
|
765
|
+
{ id: "v1.0:GET:/identity/riskPrevention/webApplicationFirewallVerifications/{webApplicationFirewallVerificationModel-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_VERIFICATION_FIELDS,
|
|
766
|
+
access: "D RiskPreventionProviders.Read.All (RiskPreventionProviders.ReadWrite.All is the documented higher-privileged alternative). Delegated callers pass it as --scopes; delegated access additionally needs a directory role that can read risk-prevention configuration (Security Reader is the least-privileged read-only role); personal Microsoft accounts are not supported and Graph documents no supported application permission, so application profiles are refused before credentials. No P1/P2 prerequisite is stated for this read.",
|
|
767
|
+
delegatedOnly: true,
|
|
768
|
+
note: "The get documents $expand only; $select is reviewed here as baseline single-resource support and $expand stays unreviewed. verificationResult and verifiedDetails ride whole as complex objects. The row never carries provider detail: the provider navigation has its own sub-read. Workforce context only; verification submission stays scheduled.",
|
|
769
|
+
sources: ["https://learn.microsoft.com/graph/api/webapplicationfirewallverificationmodel-get?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/webapplicationfirewallverificationmodel?view=graph-rest-1.0"] },
|
|
770
|
+
{ id: "v1.0:GET:/identity/riskPrevention/webApplicationFirewallVerifications/{webApplicationFirewallVerificationModel-id}/provider", kind: "single", query: SINGLE_QUERY, fields: KNOWN_WAF_FIELDS, keepODataType: true,
|
|
771
|
+
access: "D RiskPreventionProviders.Read.All (RiskPreventionProviders.ReadWrite.All is the documented higher-privileged alternative). Delegated callers pass it as --scopes; delegated access additionally needs a directory role that can read risk-prevention configuration (Security Reader is the least-privileged read-only role); personal Microsoft accounts are not supported and Graph documents no supported application permission, so application profiles are refused before credentials. No P1/P2 prerequisite is stated for this read.",
|
|
772
|
+
delegatedOnly: true,
|
|
773
|
+
note: "No provider-navigation operation page exists; access follows the WAF provider-get contract and the verificationModel resource reference. Akamai clientSecret/clientToken/accessToken and Cloudflare apiToken are never projected: all four authenticate provider APIs. Workforce context only.",
|
|
774
|
+
sources: ["https://learn.microsoft.com/graph/api/webapplicationfirewallprovider-get?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/webapplicationfirewallverificationmodel?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/webapplicationfirewallprovider?view=graph-rest-1.0"] },
|
|
554
775
|
{ id: "v1.0:GET:/identityGovernance/accessReviews/definitions", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_DEFINITION_FIELDS,
|
|
555
776
|
access: "D/A AccessReview.Read.All. Delegated callers pass it as --scopes; delegated access additionally needs a supported Entra role (group/app reviews: review creator, Global Reader, Security Reader, User Administrator, Identity Governance Administrator or Security Administrator; Entra-role reviews: Security Reader, Identity Governance Administrator, Privileged Role Administrator or Security Administrator); personal Microsoft accounts are not supported.",
|
|
556
777
|
note: "Definitions are review schedules (a series), never their occurrences; access reviews need P2 or ID Governance depending on capability.",
|
|
@@ -690,6 +911,30 @@ export const REVIEWED_ROUTES = [
|
|
|
690
911
|
access: "D/A LifecycleWorkflows-Reports.Read.All (LifecycleWorkflows.Read.All or LifecycleWorkflows.ReadWrite.All for richer detail). Delegated callers pass one as --scopes; delegated access additionally needs Global Reader or Lifecycle Workflows Administrator; personal Microsoft accounts are not supported.",
|
|
691
912
|
note: "No taskReport-nested operation page exists; access follows the taskReports list contract with the top-level taskdefinition-get contract (which documents LifecycleWorkflows.Read.All for its own route) and the taskDefinition resource reference. No query parameters are reviewed here, so whole rows arrive and are projected locally. Lifecycle workflows need Microsoft Entra ID Governance or Microsoft Entra Suite.",
|
|
692
913
|
sources: ["https://learn.microsoft.com/graph/api/identitygovernance-workflow-list-taskreports?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/identitygovernance-taskdefinition-get?view=graph-rest-1.0"] },
|
|
914
|
+
{ id: "v1.0:GET:/identityGovernance/lifecycleWorkflows/workflows/{workflow-id}/runs/{run-id}/userProcessingResults", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_USER_PROCESSING_FIELDS,
|
|
915
|
+
access: "D/A LifecycleWorkflows-Reports.Read.All (LifecycleWorkflows.Read.All or LifecycleWorkflows.ReadWrite.All for richer detail). Delegated callers pass one as --scopes; delegated access additionally needs Global Reader or Lifecycle Workflows Administrator; personal Microsoft accounts are not supported.",
|
|
916
|
+
note: "Filtering passes through as plain $filter with no $count or ConsistencyLevel contract ($search/$orderby/$expand stay unreviewed). Run user processing results are personal data: defaults carry status and counts only and the subject link needs $expand and stays out. Lifecycle workflows need Microsoft Entra ID Governance or Microsoft Entra Suite.",
|
|
917
|
+
sources: ["https://learn.microsoft.com/graph/api/identitygovernance-run-list-userprocessingresults?view=graph-rest-1.0"] },
|
|
918
|
+
{ id: "v1.0:GET:/identityGovernance/lifecycleWorkflows/workflows/{workflow-id}/runs/{run-id}/userProcessingResults/{userProcessingResult-id}", kind: "single", query: SINGLE_QUERY, fields: KNOWN_USER_PROCESSING_FIELDS,
|
|
919
|
+
access: "D/A LifecycleWorkflows-Reports.Read.All (LifecycleWorkflows.Read.All or LifecycleWorkflows.ReadWrite.All for richer detail). Delegated callers pass one as --scopes; delegated access additionally needs Global Reader or Lifecycle Workflows Administrator; personal Microsoft accounts are not supported.",
|
|
920
|
+
note: "The userprocessingresult-get page covers this run-nested single directly. Run user processing results are personal data: defaults carry status and counts only and the subject link stays out. Lifecycle workflows need Microsoft Entra ID Governance or Microsoft Entra Suite.",
|
|
921
|
+
sources: ["https://learn.microsoft.com/graph/api/identitygovernance-userprocessingresult-get?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/identitygovernance-userprocessingresult?view=graph-rest-1.0"] },
|
|
922
|
+
{ id: "v1.0:GET:/identityGovernance/lifecycleWorkflows/workflows/{workflow-id}/runs/{run-id}/subjectProcessingResults", kind: "collection", query: ["$filter"], fields: KNOWN_SUBJECT_PROCESSING_FIELDS,
|
|
923
|
+
access: "D/A LifecycleWorkflows-Reports.Read.All (LifecycleWorkflows.Read.All or LifecycleWorkflows.ReadWrite.All for richer detail). Delegated callers pass one as --scopes; delegated access additionally needs Global Reader or Lifecycle Workflows Administrator; personal Microsoft accounts are not supported.",
|
|
924
|
+
note: "Graph documents $count/$filter/$orderby/$expand but not $select here, so only $filter is reviewed and rows arrive whole. Run subject processing results are personal data: defaults carry subject type, status and counts only and the subject navigation stays out. Lifecycle workflows need Microsoft Entra ID Governance or Microsoft Entra Suite.",
|
|
925
|
+
sources: ["https://learn.microsoft.com/graph/api/identitygovernance-run-list-subjectprocessingresults?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/identitygovernance-subjectprocessingresult?view=graph-rest-1.0"] },
|
|
926
|
+
{ id: "v1.0:GET:/identityGovernance/lifecycleWorkflows/workflows/{workflow-id}/runs/{run-id}/subjectProcessingResults/{subjectProcessingResult-id}", kind: "single", query: [], fields: KNOWN_SUBJECT_PROCESSING_FIELDS,
|
|
927
|
+
access: "D/A LifecycleWorkflows-Reports.Read.All (LifecycleWorkflows.Read.All or LifecycleWorkflows.ReadWrite.All for richer detail). Delegated callers pass one as --scopes; delegated access additionally needs Global Reader or Lifecycle Workflows Administrator; personal Microsoft accounts are not supported.",
|
|
928
|
+
note: "The subjectprocessingresult-get page covers this run-nested single directly and documents $expand only, so whole rows are reviewed here and the subject navigation stays out. Run subject processing results are personal data: defaults carry subject type, status and counts only. Lifecycle workflows need Microsoft Entra ID Governance or Microsoft Entra Suite.",
|
|
929
|
+
sources: ["https://learn.microsoft.com/graph/api/identitygovernance-subjectprocessingresult-get?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/identitygovernance-subjectprocessingresult?view=graph-rest-1.0"] },
|
|
930
|
+
{ id: "v1.0:GET:/identityGovernance/lifecycleWorkflows/workflows/{workflow-id}/runs/{run-id}/taskProcessingResults", kind: "collection", query: COLLECTION_QUERY, fields: KNOWN_TASK_PROCESSING_FIELDS,
|
|
931
|
+
access: "D/A LifecycleWorkflows-Reports.Read.All (LifecycleWorkflows.Read.All or LifecycleWorkflows.ReadWrite.All for richer detail). Delegated callers pass one as --scopes; delegated access additionally needs Global Reader or Lifecycle Workflows Administrator; personal Microsoft accounts are not supported.",
|
|
932
|
+
note: "Filtering passes through as plain $filter with no $count or ConsistencyLevel contract ($search/$orderby/$expand stay unreviewed). Run task processing results carry one task's outcome with failure detail; the subject, task and workflowSubject navigations need $expand and stay out. Lifecycle workflows need Microsoft Entra ID Governance or Microsoft Entra Suite.",
|
|
933
|
+
sources: ["https://learn.microsoft.com/graph/api/identitygovernance-run-list-taskprocessingresults?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/identitygovernance-taskprocessingresult?view=graph-rest-1.0"] },
|
|
934
|
+
{ id: "v1.0:GET:/identityGovernance/lifecycleWorkflows/workflows/{workflow-id}/runs/{run-id}/taskProcessingResults/{taskProcessingResult-id}", kind: "single", query: [], fields: KNOWN_TASK_PROCESSING_FIELDS,
|
|
935
|
+
access: "D/A LifecycleWorkflows-Reports.Read.All (LifecycleWorkflows.Read.All or LifecycleWorkflows.ReadWrite.All for richer detail). Delegated callers pass one as --scopes; delegated access additionally needs Global Reader or Lifecycle Workflows Administrator; personal Microsoft accounts are not supported.",
|
|
936
|
+
note: "No operation-level get page exists; access follows the run task-list contract and the taskProcessingResult resource reference. No query parameters are reviewed here, so whole rows arrive and are projected locally; the subject, task and workflowSubject navigations stay out. Lifecycle workflows need Microsoft Entra ID Governance or Microsoft Entra Suite.",
|
|
937
|
+
sources: ["https://learn.microsoft.com/graph/api/identitygovernance-run-list-taskprocessingresults?view=graph-rest-1.0", "https://learn.microsoft.com/graph/api/resources/identitygovernance-taskprocessingresult?view=graph-rest-1.0"] },
|
|
693
938
|
];
|
|
694
939
|
function splitPath(path) {
|
|
695
940
|
return path.split("/").filter(segment => segment.length > 0);
|
|
@@ -814,9 +1059,9 @@ function reviewedFields(route, value) {
|
|
|
814
1059
|
kept["@odata.type"] = value["@odata.type"];
|
|
815
1060
|
return kept;
|
|
816
1061
|
}
|
|
817
|
-
// String truncation at the output boundary,
|
|
818
|
-
//
|
|
819
|
-
// session and row caps are unaffected. Plain objects and arrays only.
|
|
1062
|
+
// String truncation at the output boundary, matching the 500-char rule used
|
|
1063
|
+
// by every Entra command. --full disables truncation; redaction already ran
|
|
1064
|
+
// in the session and row caps are unaffected. Plain objects and arrays only.
|
|
820
1065
|
function truncateForOutput(value, full) {
|
|
821
1066
|
if (typeof value === "string") {
|
|
822
1067
|
if (full || value.length <= TRUNCATE_AT)
|
|
@@ -924,7 +1169,7 @@ export async function runApiGet(args, deps) {
|
|
|
924
1169
|
const body = await session.execute({ profile: args.profile, operation, params, query, scopes });
|
|
925
1170
|
const shaped = truncateForOutput(reviewedFields(outputRoute, body), full);
|
|
926
1171
|
const record = isRecord(shaped.value) ? shaped.value : { value: shaped.value };
|
|
927
|
-
return shaped.truncated ? { ...record, help: ["Strings truncated at
|
|
1172
|
+
return shaped.truncated ? { ...record, help: ["Strings truncated at 500 chars; re-run with --full"] } : record;
|
|
928
1173
|
}
|
|
929
1174
|
const collected = await session.collect({ profile: args.profile, operation, params, query, scopes, limit: args.limit, cursor: args.cursor });
|
|
930
1175
|
const shaped = truncateForOutput(collected.value.map(row => reviewedFields(outputRoute, row)), full);
|
|
@@ -932,11 +1177,11 @@ export async function runApiGet(args, deps) {
|
|
|
932
1177
|
const warnings = route.warning ? { warnings: [route.warning] } : {};
|
|
933
1178
|
if (collected.complete) {
|
|
934
1179
|
return shaped.truncated
|
|
935
|
-
? { returned: value.length, complete: true, value, ...warnings, help: ["Strings truncated at
|
|
1180
|
+
? { returned: value.length, complete: true, value, ...warnings, help: ["Strings truncated at 500 chars; re-run with --full"] }
|
|
936
1181
|
: { returned: value.length, complete: true, value, ...warnings };
|
|
937
1182
|
}
|
|
938
1183
|
const hint = "Resume the same path, profile and scopes with --cursor - and supply the cursor token on stdin; use --limit <rows> or --all";
|
|
939
|
-
const help = shaped.truncated ? [hint, "Strings truncated at
|
|
1184
|
+
const help = shaped.truncated ? [hint, "Strings truncated at 500 chars; re-run with --full"] : [hint];
|
|
940
1185
|
return { returned: value.length, complete: false, reason: collected.reason, value, ...warnings, cursor: collected.cursor, help };
|
|
941
1186
|
}
|
|
942
1187
|
// Minimal HTTPS transport: sends only what the session authorized (GET on the
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Session-start hook entry point: print the local-only ambient summary and
|
|
3
|
+
// always exit 0 on config state, never loudly, so agent startup never breaks.
|
|
4
|
+
// Unknown argv fails loud with exit 2 instead of a silent wrong summary.
|
|
5
|
+
// Static imports are avoided so a broken install still reaches the fallback.
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
if (args.length === 1 && args[0] === "--help") {
|
|
8
|
+
process.stdout.write("mg-axi-hook: print the local-only mg-axi session-start summary (configured profiles, auth-cache presence, version)\nusage: mg-axi-hook [--help]\n");
|
|
9
|
+
}
|
|
10
|
+
else if (args.length > 0) {
|
|
11
|
+
try {
|
|
12
|
+
const { encode } = await import("@toon-format/toon");
|
|
13
|
+
process.stdout.write(`${encode({ error: `unexpected argument \`${args[0]}\` for \`mg-axi-hook\``, code: "VALIDATION_ERROR", help: ["Run `mg-axi-hook` with no arguments for the session summary"] })}\n`);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
process.stdout.write(`error: unexpected argument \`${args[0]}\` for \`mg-axi-hook\`\n`);
|
|
17
|
+
}
|
|
18
|
+
process.exitCode = 2;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
try {
|
|
22
|
+
const { VERSION } = await import("../version.js").catch(() => ({ VERSION: "unknown" }));
|
|
23
|
+
const { hookSummary } = await import("../hook.js");
|
|
24
|
+
process.stdout.write(await hookSummary({ version: VERSION }));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
process.stdout.write("mg: status unavailable\n");
|
|
28
|
+
}
|
|
29
|
+
process.exitCode = 0;
|
|
30
|
+
}
|
|
31
|
+
export {};
|