问题描述
我正在使用Azure DevOps管道部署基于Azure功能的应用程序,作为部署的一部分,还提供了所需的基础结构(使用ARM模板)。 Azure函数需要访问Microsoft Graph&SharePoint REST API,以实现以下步骤:
- Azure函数是使用系统分配的身份(MSI)创建的。
- MSI(身份)被传递到下面的PowerShell脚本,以启用对Graph&SharePoint API的访问。
$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$context.Tenant.Id.ToString(),$null,[Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never,"https://graph.microsoft.com").Accesstoken
$aadToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account,$context.Environment,$context.Tenant.Id.ToString(),"https://graph.windows.net").Accesstoken
Connect-AzureAD -AadAccesstoken $aadToken -AccountId $context.Account.Id -TenantId $context.tenant.id
$azureFunctionServicePrincipal = Get-AzureADServicePrincipal -Filter "ObjectId eq '$PrincipalId'"
#Graph service principal
$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
$GraphFilesReadWriteallAppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -in 'Files.ReadWrite.All' -and $_.AllowedMemberTypes -contains 'Application'}
New-AzureAdServiceAppRoleAssignment -ObjectId $EcaseServicePrincipal.ObjectId -PrincipalId $EcaseServicePrincipal.ObjectId -ResourceId $GraphServicePrincipal.ObjectId -Id $GraphFilesReadWriteallAppRole.Id
$SharePointOnlineservicePrinciple = Get-AzureADServicePrincipal -SearchString “Office 365 SharePoint”
$SharePointOnlinesitesReadWriteallAppRole = $SharePointOnlineservicePrinciple.AppRoles | Where-Object {$_.Value -in 'Sites.ReadWrite.All' -and $_.AllowedMemberTypes -contains 'Application'}
New-AzureAdServiceAppRoleAssignment -ObjectId $EcaseServicePrincipal.ObjectId -PrincipalId $EcaseServicePrincipal.ObjectId -ResourceId $SharePointOnlineservicePrinciple.ObjectId -Id $SharePointOnlinesitesReadWriteallAppRole.Id
由于权限不足,执行Get-AzureADServicePrincipal命令时PowerShell脚本失败,该命令在DevOps的ServiceConnection标识下执行。为ServiceConnection分配了以下附加特权,
我无法确定要成功获得GetServicePrincipal以及执行New-AzureAdServiceAppRoleAssignment cmdlet所需的其他特权。
[2020年8月31日更新] 。感谢AlleWu的解决方案,与GetServicePrincipal相关的权限问题得以解决。但是,尽管有以下权限,但执行NewServicePrincipalAppRoleAssignment的权限问题仍然存在,我错过了一些步骤。另外,我已经使ServiceConnection对象成为ResourceGroup的所有者,但这也失败了。
NewServicePrincipalAppRoleAssignment执行错误日志:
2020-08-31T05:24:55.5613075Z ##[debug]+ New-AzureAdServiceAppRoleAssignment -ObjectId $EcaseServicePrincipal. ...
2020-08-31T05:24:55.5639370Z ##[debug]+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2020-08-31T05:24:55.5721318Z ##[debug] + CategoryInfo : NotSpecified: (:) [New-AzureADServiceAppRoleAssignment],ApiException
2020-08-31T05:24:55.5744883Z ##[debug] + FullyQualifiedErrorId : Microsoft.Open.AzureAD16.Client.ApiException,Microsoft.Open.AzureAD16.PowerShell.NewServ icePrincipalAppRoleAssignment
2020-08-31T05:24:55.5765560Z ##[debug]
2020-08-31T05:24:55.5834409Z ##[debug]Script stack trace:
2020-08-31T05:24:55.5976760Z ##[debug]at <ScriptBlock>,D:\a\1\s\azure.pipelines\pwsh\provision_service_principle_for_sharepoint_graph.ps1: line 23
2020-08-31T05:24:55.6006045Z ##[debug]at <ScriptBlock>,<No file>: line 1
2020-08-31T05:24:55.6029248Z ##[debug]at <ScriptBlock>,D:\a\_tasks\AzurePowerShell_72a1931b-effb-4d2e-8fd8-f8472a07cb62\4.173.1\azurepowershell.ps1: line 229
2020-08-31T05:24:55.6188575Z ##[debug]at <ScriptBlock>,D:\a\_tasks\AzurePowerShell_72a1931b-effb-4d2e-8fd8-f8472a07cb62\4.173.1\azurepowershell.ps1: line 225
2020-08-31T05:24:55.6219503Z ##[debug]at <ScriptBlock>,<No file>: line 1
2020-08-31T05:24:55.6243577Z ##[debug]at <ScriptBlock>,<No file>: line 22
2020-08-31T05:24:55.6281986Z ##[debug]at <ScriptBlock>,<No file>: line 18
2020-08-31T05:24:55.6331521Z ##[debug]at <ScriptBlock>,<No file>: line 1
2020-08-31T05:24:55.6497107Z ##[debug]Exception:
2020-08-31T05:24:55.6577566Z ##[debug]Microsoft.Open.AzureAD16.Client.ApiException: Error occurred while executing NewServicePrincipalAppRoleAssignment
2020-08-31T05:24:55.6607345Z ##[debug]Code: Authorization_RequestDenied
2020-08-31T05:24:55.6683059Z ##[debug]Message: Insufficient privileges to complete the operation.
2020-08-31T05:24:55.6712669Z ##[debug]RequestId: 14e5694e-bfde-404f-a441-4543871b1e56
2020-08-31T05:24:55.6760142Z ##[debug]DateTimeStamp: Mon,31 Aug 2020 05:24:53 GMT
2020-08-31T05:24:55.6794376Z ##[debug]HttpStatusCode: Forbidden
2020-08-31T05:24:55.6818439Z ##[debug]HttpStatusDescription: Forbidden
2020-08-31T05:24:55.6842869Z ##[debug]HttpResponseStatus: Completed
2020-08-31T05:24:55.6890342Z ##[debug]
2020-08-31T05:24:55.6915727Z ##[debug] at Microsoft.Open.AzureAD16.Client.Configuration.<>c.<.cctor>b__47_0(String methodName,IRestResponse response) in X:\bt\1137570\repo\src\dev\PowerShell.V2\AzureAD16.Client\Client\Configuration.cs:line 188
2020-08-31T05:24:55.6947059Z ##[debug] at Microsoft.Open.AzureAD16.Api.ServicePrincipalApi.NewServicePrincipalAppRoleAssignmentWithHttpInfo(String tenantId,String objectId,String authorization,String cmdletName,String clientRequestId,String apiVersion,AppRoleAssignment appRoleAssignment) in X:\bt\1137570\repo\src\dev\PowerShell.V2\AzureAD16.Client\Api\ServicePrincipalApi.cs:line 4006
2020-08-31T05:24:55.6977721Z ##[debug] at Microsoft.Open.AzureAD16.PowerShell.NewServicePrincipalAppRoleAssignment.ProcessRecord() in X:\bt\1137570\repo\src\dev\PowerShell.V2\AzureAD16.PowerShell\AzureAD16.PowerShell.AutoGen\API\ServicePrincipalApi.cs:line 2019
2020-08-31T05:24:55.7008421Z ##[debug] at System.Management.Automation.CommandProcessor.ProcessRecord()
2020-08-31T05:24:55.7366976Z ##[error]Error occurred while executing NewServicePrincipalAppRoleAssignment
Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.
RequestId: 14e5694e-bfde-404f-a441-4543871b1e56
DateTimeStamp: Mon,31 Aug 2020 05:24:53 GMT
HttpStatusCode: Forbidden
HttpStatusDescription: Forbidden
更新2020年第一套产品:上面建议的替代解决方案有效,下面我更新了用于提供所需权限的脚本,
$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$graphToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account,"https://graph.windows.net").Accesstoken
Connect-AzureAD -AadAccesstoken $aadToken -AccountId $context.Account.Id -TenantId $context.tenant.id
$webAppServicePrincipal = Get-AzureADServicePrincipal -Filter "ObjectId eq '$PrincipalId'" #$PrincipalId is the ObjectId of the webApp instance
$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
$GraphFilesReadWriteallAppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -in 'Files.ReadWrite.All' -and $_.AllowedMemberTypes -contains 'Application'}
#It appears that the Azure DevOps's service connection need to have Global Administrator permissions to successfully execute the below statement; which is not recommended,hence,this is implemented calling Graph API
#New-AzureAdServiceAppRoleAssignment -ObjectId $EcaseServicePrincipal.ObjectId -PrincipalId $EcaseServicePrincipal.ObjectId -ResourceId $GraphServicePrincipal.ObjectId -Id $GraphFilesReadWriteallAppRole.Id
$resourceId = $GraphServicePrincipal.ObjectId
$body = @{
"principalId"= $webAppServicePrincipal.ObjectId
"resourceId"= $resourceId
"appRoleId"= $GraphFilesReadWriteallAppRole.Id
}
$apiUrl = "https://graph.microsoft.com/v1.0/servicePrincipals/$resourceId/appRoleAssignedTo"
Invoke-RestMethod -Uri $apiUrl -Headers @{Authorization = "Bearer $($graphToken)" } -Method POST -Body $($body | convertto-json) -ContentType "application/json"
解决方法
Get-AzureADServicePrincipal
命令正在调用Azure AD Graph而不是Microsoft Graph。
GET https://graph.windows.net/{tenant id}/servicePrincipals?api-version=1.6 HTTP/1.1
因此,您应授予Azure AD Graph权限:
更新:
发现了一些有趣的东西:
尽管我将所有AAD Graph应用程序权限分配给了服务主体,但它仍然显示“权限不足,无法完成操作”。
因此,我使用另一种方法:将 Global Administrator 角色分配给该服务主体。但它会延迟大约10-15分钟。然后,服务主体可以成功执行New-AzureAdServiceAppRoleAssignment
。
我还以 Application Administrator 角色进行了测试,但是它不起作用。我认为AAD Graph会有一些更改,因此不会得到维护。因此,不建议使用它。
作为一种解决方法,您可以在Powershell脚本中为服务主体调用Microsoft Graph API:Grant an appRoleAssignment。