2

更新:我发现问题与IncludeClassicAdministrators参数无关 - 没有那个问题仍然会发生。我已经相应地更新了这个问题。

背景
我正在编写一个 Azure 自动化脚本来监控谁有权访问我的订阅。我打电话Get-AzureRmRoleAssignment来获取管理员列表。当我在本地运行我的脚本并以我自己的身份进行身份验证时,它工作正常。当我在自动化中运行它时,我正在使用服务主体进行身份验证,并且由于Access denied to the specified API version失败。

详细信息
我启用了调试输出,我可以看到Get-AzureRmRoleAssignment进行了 3 个 API 调用:

GET https://management.azure.com/subscriptions/xxx/providers/Microsoft.Authorization
    /roleAssignments?api-version=2015-07-01 

GET https://management.azure.com//subscriptions/xxx/providers/Microsoft.Authorization
    /roleDefinitions?$filter=atScopeAndBelow()&api-version=2015-07-01

POST https://graph.windows.net/xxx/getObjectsByObjectIds?api-version=1.42-previewInternal 
{
  "objectIds": [
    "282e2807-cbd9-43bb-89c2-edc3122fcc04",
    "b3a38989-fcf1-4569-b1a6-444e1cd583b6",
    "6b0b69bb-49d8-48a6-a740-8c354eb575ea",
    "6b0b69bb-49d8-48a6-a740-8c354eb575ea",
    "90c78c97-1b3b-444f-a3bb-9fb9dfdb3455",
    "7db061f0-361d-4148-a5ef-0a37b138f37c",
    "844d81c7-7027-44c3-899d-21e90a7e599d",
    "6b0b69bb-49d8-48a6-a740-8c354eb575ea"
  ],
  "includeDirectoryObjectReferences": true
}

在 Azure 自动化中,这是最后一次调用(获取第一次调用返回的用户对象 ID 的用户详细信息)失败:

Status Code:
Forbidden

Headers:
ocp-aad-diagnostics-server-name: CL43Rj9/Eg1H2aYXpRQBM3J4ssdQAWJx32NV+f61Yn4=
request-id                    : 0a184c82-1dd0-4f29-9192-aa746dff470a
client-request-id             : e94a29bf-9846-427e-b958-8a2f9d3a32e3
x-ms-dirapi-data-contract-version: 1.42-previewInternal
ocp-aad-session-key           : inmY52ItGZojOuCWsXYSgmNBsJZIQXlg8-l0FLzrvOnftsGwyOfzjmNtXMfLiXQqOp32Pk1n1GjvnvbJdT0Pak6d
7NwIFNIy0tUBep-rTRH__HFt_Kb_2ffSgOPlJSe-.ms4g4jKJV0H4VNYwMDPJljQFyNDjrw42XxrOKmkPXHU
Strict-Transport-Security     : max-age=31536000; includeSubDomains
Access-Control-Allow-Origin   : *
Duration                      : 1323869
Cache-Control                 : private
Server                        : Microsoft-IIS/8.5
X-AspNet-Version              : 4.0.30319
X-Powered-By                  : ASP.NET,ASP.NET
Date                          : Wed, 24 Feb 2016 02:45:55 GMT

Body:
{
  "odata.error": {
    "code": "Authentication_Unauthorized",
    "message": {
      "lang": "en",
      "value": "Access denied to the specified API version."
    }
  }
}

我在本地运行时看到完全相同的调用,所以我认为这不是版本问题。(我正在使用图库中的 MSOnline 模块。)

我在想我需要向我的服务主体授予一些额外的权限,但不确定哪些权限。我添加了以下所有权限,但仍然收到相同的错误:

Windows Azure Active Directory
应用程序权限

  • 读/写目录数据
  • 读取目录数据

委托权限

  • 读取目录数据
  • 阅读所有用户的完整个人资料
  • 阅读所有用户的基本资料

Windows Azure 服务管理 API
委派权限

  • 以组织用户身份访问 Azure 服务管理

Microsoft Graph
应用程序权限

  • 读取目录数据
4

3 回答 3

1

在使用服务主体进行身份验证时使用调用 Graph API 的 cmdlet 时,这是一个已知问题。

https://github.com/Azure/azure-powershell/issues/1896

于 2016-06-16T21:28:30.550 回答
0

服务主体不能是经典管理员,但可以是所有者。所有者拥有与经典管理员相同的权限。因此,将服务主体设置为订阅的所有者应该可以解决问题。

于 2016-03-01T18:57:03.430 回答
0

我不认为服务主体在这种情况下会起作用,因为获取管理员列表需要共同管理员权限,这意味着您需要为默认 Active Directory 创建一个无 Microsoft 帐户和禁用 MFA 的用户帐户(服务管理员可以,但如果需要,您可以拥有一个全局管理员),并将其作为共同管理员添加到您的订阅管理员。

在您的自动化运行手册中,您需要使用凭据登录。

有关详细信息,请参阅在 Azure 自动化中配置 Azure 自动化凭据资产





在对 Graph API 进行了几次挖掘之后,我发现Get-AzureRmRoleAssignment. 这是我用来测试 Graph API 的 powerShell 脚本:

try{
    $subscription = Get-AzureRmSubscription
}
catch{
    Login-AzureRmAccount
    $subscription = Get-AzureRmSubscription
}

$tenantID = $subscription.TenantId
$authString = "https://login.microsoftonline.com/" + $tenantID

$clientId = "<The client id of your AD application>"
$key = "<The key of the above client>"

$authenticationContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext ($authString, $false)

$clientCred = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential ($clientId, $key)

$resource = "https://graph.windows.net"

$authenticationResult = $authenticationContext.AcquireToken($resource, $clientCred);

$authHeader = $authenticationResult.AccessTokenType + " " + $authenticationResult.AccessToken

$headers = @{"Authorization"=$authHeader; "Content-Type"="application/json"}

$result = Invoke-RestMethod -Method Post -Uri "https://graph.windows.net/$tenantID/getObjectsByObjectIds?api-version=beta" -Headers $headers -InFile .\objectIds.json

$result.value

注意:在 中.\objectIds.json,请存储您从调试模式获得的 json 请求正文。

使用 api-version=beta,在一个订阅中,它给了我错误{"odata.error":{"code":"Authorization_RequestDenied","message":{"lang":"en","value":"Insufficient privileges to complete the operation."}}},而在另一个订阅中,它运行完美。

关于这2个订阅的区别,我没有权限访问第一个订阅的默认目录下的用户列表;另一方面,我确实可以访问第二个订阅的默认目录中的用户列表。

请尝试我提供的脚本并告诉我您的结果。

此外,如果您只需要经典管理员列表,以下脚本就足够了。上述问题仅在您尝试获取角色分配时发生。

$tenantID = "<the tenant id of your subscription>"
$authString = "https://login.windows.net/" + $tenantID

$clientId = "<the client id of your AD application>"
$key = "<the key of the above client>"

$resource = "https://management.core.windows.net/"

$secpasswd = ConvertTo-SecureString $key -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($clientId, $secpasswd)

try{
    $subscription = Get-AzureRmSubscription
}
catch{
    Login-AzureRmAccount -Credential $mycreds -Tenant $tenantID -ServicePrincipal
    $subscription = Get-AzureRmSubscription
}

$subscriptionId = $subscription.subscriptionId

$authenticationContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext ($authString, $false)

$clientCred = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential ($clientId, $key)

$authenticationResult = $authenticationContext.AcquireToken($resource, $clientCred);

$authHeader = $authenticationResult.AccessTokenType + " " + $authenticationResult.AccessToken

$headers = @{"Authorization"=$authHeader; "Content-Type"="application/json"}

$result = Invoke-RestMethod -Method Get -Uri "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Authorization/classicAdministrators?api-version=2015-06-01" -Headers $headers

$result.value
于 2016-02-24T08:43:48.257 回答