如何使用 Azure Python SDK 将 principal_id 转换为用户名

How do you turn a principal_id into a username using the Azure Python SDK

使用 Azure Python SDK 我正在尝试构建一个脚本来审核我们的各种用户角色授权。我可以使用以下方法提取角色分配列表:

authorizationClient = AuthorizationManagementClient(credential, subscription_id)
roles = authorizationClient.role_assignments.list()

这行得通,我得到了一个字典列表,其中似乎包含了我需要的所有信息,除了 principal_name。响应示例:

{'additional_properties': {}, 'id': '/providers/Microsoft.Management/managementGroups/<group_ID>/providers/Microsoft.Authorization/roleAssignments/<role_ID>', 'name': '<role_ID>', 'type': 'Microsoft.Authorization/roleAssignments', 'scope': '/providers/Microsoft.Management/managementGroups/<scope_ID>', 'role_definition_id': '/subscriptions/<subscription_ID>/providers/Microsoft.Authorization/roleDefinitions/<role_def_id>', 'principal_id': '<principal_ID>', 'principal_type': 'Group', 'can_delegate': None}

使用 Azure Python SDK,有没有办法在给定 principal_id 的情况下查找 principal_name?

我已经阅读了几个小时的 SDK 文档,但似乎找不到答案。我所能找到的是 azure cli 默认吐出 principal_id 和 principal_name,但 SDK 没有。在此感谢任何帮助。

您需要使用 azure-graphrbac 包: https://pypi.org/project/azure-graphrbac/

用法示例:

    objects = graphrbac_client.objects.get_objects_by_object_ids({
        'object_ids': [app.object_id],
        'types': ['ServicePrincipal']
    })

还有一个过滤器语法。我没有用 ID 过滤的那个,但这给了你一个想法:

    users = graphrbac_client.users.list(
        filter="displayName eq 'Test Buddy'"
    )

graphrbac 文档: https://azuresdkdocs.blob.core.windows.net/$web/python/azure-graphrbac/0.61.1/azure.graphrbac.html

一些广泛的单元测试可以提供帮助: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/graphrbac/azure-graphrbac/tests/test_graphrbac.py

RestAPI 文档可以让您深入了解 SDK 的功能: https://docs.microsoft.com/en-us/previous-versions/azure/ad/graph/api/api-catalog

(我在 MS Python SDK 团队工作)

一个完整的Python例子:

# requirements.txt

azure-common==1.1.27
azure-core==1.19.0
azure-graphrbac==0.61.1
azure-identity==1.6.1
azure-mgmt-authorization==2.0.0
azure-mgmt-core==1.3.0
msrestazure==0.6.4
"""wrapper.py

   Copy from this answer  
"""
"""main.py"""
import sys

from azure.graphrbac import GraphRbacManagementClient
from azure.graphrbac.models import GetObjectsParameters
from azure.identity import DefaultAzureCredential
from azure.mgmt.authorization import AuthorizationManagementClient

from wrapper import CredentialWrapper

CREDENTIALS = DefaultAzureCredential()

# Without the resource_id arg, you get an error:
# msrestazure.azure_exceptions.CloudError: 401 Client Error: Unauthorized for url...
GRAPH_CREDENTIALS = CredentialWrapper(
    resource_id="https://graph.windows.net",
)


def main(tenant_id, subscription_id):
    auth_client = AuthorizationManagementClient(
        credential=CREDENTIALS, subscription_id=subscription_id
    )

    # https://docs.microsoft.com/en-us/python/api/azure-mgmt-authorization/azure.mgmt.authorization.v2015_07_01.models.roleassignmentlistresult?view=azure-python
    assignments_list = list(auth_client.role_assignments.list())

    role_definitions = list(
        auth_client.role_definitions.list(
            scope="/subscriptions/" + subscription_id
        )
    )

    # A lookup table of role definition IDs and their names.
    role_def_dict = {x.id: x.role_name for x in role_definitions}

    graph_client = GraphRbacManagementClient(
        credentials=GRAPH_CREDENTIALS, tenant_id=tenant_id
    )

    for assignment in assignments_list:
        
        # Look up the role's name using its ID.
        role_name = role_def_dict[assignment.properties.role_definition_id]

        # Barely any documentation on this function. I've lifted the code from the CLI.
        params = GetObjectsParameters(
            include_directory_object_references=True,
            object_ids=[assignment.properties.principal_id],
        )

        # Likewise this function.
        results = list(graph_client.objects.get_objects_by_object_ids(params))

        # This is the group/user/managed identity that has been assigned the role
        assignee = results[0]

        print("{} : {}".format(results[0].display_name, role_name))


if __name__ == "__main__":
    main(sys.argv[1], sys.argv[2])
python -m main "<your-tenant-id>" "<your-subscription-id>"