You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MS Graph Beta API条件访问策略监控:GUID替换与权限范围咨询

关于MS Graph Beta API获取条件访问策略时替换GUID为名称的问题

我正在开发监控条件访问策略的仪表板API查询,调用接口正常,但返回结果里的用户和角色都是GUID(见示例输出),实用性很差。

示例输出

{
  "id": "8193577f-eed0-4dcd-8570-bea5dde99caf",
  "templateId": "c7503427-338e-4c5e-902d-abe252abfb43",
  "displayName": "Require multifactor authentication for admins",
  "createdDateTime": "2025-02-18T16:45:43.440382Z",
  "modifiedDateTime": null,
  "state": "enabled",
  "partialEnablementStrategy": null,
  "sessionControls": null,
  "conditions": {
    "userRiskLevels": [],
    "signInRiskLevels": [],
    "clientAppTypes": ["all"],
    "platforms": null,
    "locations": null,
    "times": null,
    "deviceStates": null,
    "devices": null,
    "clientApplications": null,
    "applications": {
      "includeApplications": ["All"],
      "excludeApplications": [],
      "includeUserActions": [],
      "includeAuthenticationContextClassReferences": [],
      "applicationFilter": null
    },
    "users": {
      "includeUsers": [],
      "excludeUsers": [
        "2c5b3083-c60b-41ad-9343-eb3bc01d444a" // GUID格式用户ID
      ],
      "includeGroups": [],
      "excludeGroups": [],
      "includeRoles": [
        "62e90394-69f5-4237-9190-012177145e10", // GUID格式角色ID
        "194ae4cb-b126-40b2-bd5b-6091b380977d",
        "f28a1f50-f6e7-4571-818b-6a12f2af6b6c",
        "29232cdf-9323-42fd-ade2-1d097af3e4de",
        "b1be1c3e-b65d-4f19-8427-f6fa0d97feb9",
        "729827e3-9c14-49f7-bb1b-9608f156bbb8"
      ]
    }
  }
}

核心问题

使用MS Graph Beta API,除了Directory.Read.All和Policies.Read.All权限,有没有额外权限能让接口直接返回用户/角色的名称?还是必须提取所有ID后手动匹配回填?

我的API调用代码

const handleGetPolicies = async () => {
  if (isAuthenticated) {
    setIsFetching(true);
    try {
      // 获取条件访问策略
      const result = await callMsGraph('/policies/conditionalAccessPolicies');

      // 待实现的替换逻辑函数
      const updatedResult = await replaceUserIdsWithDisplayNames(result);

      setResponse(JSON.stringify(updatedResult, null, 2)); 
    } catch (error) {
      setResponse('获取策略失败: ' + (error as Error).message);
    }
    setIsFetching(false);
  } else {
    setResponse('用户未认证');
  }
};

解答

目前MS Graph Beta的/policies/conditionalAccessPolicies接口不支持直接返回用户/角色的名称,无论添加什么额外权限都无法实现。你必须手动提取GUID,单独调用API获取对应名称后回填到结果中。

具体实现步骤

  1. 收集所有需要替换的ID:遍历每个策略的conditions.users字段,收集includeUsers、excludeUsers、includeRoles、excludeRoles里的所有GUID(跳过"All"这类特殊值)。
  2. 批量查询用户和角色信息:
    • 查询用户:调用/users?$filter=id in ('guid1','guid2')&$select=id,displayName,批量获取用户ID对应的显示名称。
    • 查询目录角色:调用/directoryRoles?$filter=id in ('guid1','guid2')&$select=id,displayName,注意CA策略中的角色ID是目录角色实例的ID,而非角色定义ID。
  3. 建立映射表并替换:将查询到的ID和名称存入对象映射,遍历原策略结果,把所有GUID替换为对应的名称。

替换函数示例代码

const replaceUserIdsWithDisplayNames = async (policies) => {
  // 收集所有需要查询的ID
  const userIds = new Set();
  const roleIds = new Set();

  policies.forEach(policy => {
    const { users } = policy.conditions || {};
    if (!users) return;

    // 收集用户ID
    [...(users.includeUsers || []), ...(users.excludeUsers || [])]
      .filter(id => id !== 'All' && id !== 'None')
      .forEach(id => userIds.add(id));
    
    // 收集角色ID
    [...(users.includeRoles || []), ...(users.excludeRoles || [])]
      .filter(id => id !== 'All' && id !== 'None')
      .forEach(id => roleIds.add(id));
  });

  // 批量查询用户
  const userMap = {};
  if (userIds.size > 0) {
    const userIdsArr = Array.from(userIds);
    // 分批处理,因为in操作符最多支持15个ID
    const batches = [];
    for (let i = 0; i < userIdsArr.length; i += 15) {
      batches.push(userIdsArr.slice(i, i + 15));
    }

    for (const batch of batches) {
      const filter = `id in (${batch.map(id => `'${id}'`).join(',')})`;
      const users = await callMsGraph(`/users?$filter=${filter}&$select=id,displayName`);
      users.value.forEach(user => {
        userMap[user.id] = user.displayName;
      });
    }
  }

  // 批量查询角色
  const roleMap = {};
  if (roleIds.size > 0) {
    const roleIdsArr = Array.from(roleIds);
    const batches = [];
    for (let i = 0; i < roleIdsArr.length; i += 15) {
      batches.push(roleIdsArr.slice(i, i + 15));
    }

    for (const batch of batches) {
      const filter = `id in (${batch.map(id => `'${id}'`).join(',')})`;
      const roles = await callMsGraph(`/directoryRoles?$filter=${filter}&$select=id,displayName`);
      roles.value.forEach(role => {
        roleMap[role.id] = role.displayName;
      });
    }
  }

  // 替换原结果中的GUID
  return policies.map(policy => {
    const newPolicy = { ...policy };
    const { users } = newPolicy.conditions || {};
    if (!users) return newPolicy;

    // 替换用户ID
    ['includeUsers', 'excludeUsers'].forEach(field => {
      if (users[field]) {
        users[field] = users[field].map(id => userMap[id] || id);
      }
    });

    // 替换角色ID
    ['includeRoles', 'excludeRoles'].forEach(field => {
      if (users[field]) {
        users[field] = users[field].map(id => roleMap[id] || id);
      }
    });

    return newPolicy;
  });
};

注意事项

  • 批量查询时,$filter=id in()最多支持15个ID,超过需要分批处理。
  • 确保已申请Directory.Read.All权限,否则无法查询用户和目录角色信息。
  • 可以添加缓存逻辑,对已查询过的ID进行缓存,避免重复调用API提升性能。

内容的提问来源于stack exchange,提问作者Sethe23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 00:17:35