0

在 powershell 中,我们有一个脚本,它使用资源所有者密码凭据从 Azure REST API 获取信息。

https://docs.microsoft.com/bs-latn-ba/azure/active-directory/develop/v2-oauth-ropc

该脚本适用于未启用 MFA 的用户。对于具有 MFA 的用户,它不起作用。我尝试使用我在具有 MFA 的用户帐户上创建的应用程序密码,但这也不起作用。

https://support.microsoft.com/en-au/help/12409/microsoft-account-app-passwords-and-two-step-verification

该脚本作为服务运行,因此无法进行用户交互。我们还需要使用 ROPC,因为我们需要的信息只能通过 Azure 应用程序上的委派权限获得。

有没有人有这方面的经验?

这是脚本:

$tenantid = '*************************'
$subscriptionid = '*********************'
$clientid = '***********************'
$clientsecret = '******************'
$username = '*****************'
$password = '************************'

##################################################################
##################################################################
##################################################################

$return = Invoke-Command -ScriptBlock { 
param($tenantid,$subscriptionid,$clientid,$clientsecret,$username,$password)    

Add-Type -AssemblyName System.Web

$encPass = [System.Web.HttpUtility]::UrlEncode($password)
$encScope = [System.Web.HttpUtility]::UrlEncode('https://management.azure.com/user_impersonation')
$encSecret = [System.Web.HttpUtility]::UrlEncode($clientsecret)

$body = "client_id=$clientid&scope=$encScope&username=$username&password=$encPass&grant_type=password&client_secret=$encSecret"

$auth = Invoke-WebRequest "https://login.microsoftonline.com/$tenantid/oauth2/v2.0/token" -Method Post -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing

$token = ($auth | ConvertFrom-Json).access_token
$headers = @{
    'Authorization'="Bearer $($token)"
}

$data = Invoke-WebRequest "https://management.azure.com/subscriptions/$subscriptionid/providers/Microsoft.Advisor/recommendations?api-version=2017-04-19" -Method GET -Headers $headers -UseBasicParsing

New-Object PSObject -Property @{
    content=$data.content
}

} -ArgumentList $tenantid,$subscriptionid,$clientid,$clientsecret,$username,$password

$content = $return.content

Write-Host $content

当我使用启用了 MFA 的用户时的输出:

Invoke-WebRequest : {"error":"invalid_grant","error_description":"AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to 
access '*******'.\r\nTrace ID: d9a7f9f2-c52c-40ca-b057-9513bd353900\r\nCorrelation ID: 3329e686-7bd0-409d-b7da-91e49221bacc\r\nTimestamp: 2019-10-02 
13:19:36Z","error_codes":[50076],"timestamp":"2019-10-02 
13:19:36Z","trace_id":"d9a7f9f2-c52c-40ca-b057-9513bd353900","correlation_id":"3329e686-7bd0-409d-b7da-91e49221bacc","error_uri":"https://login.microsoftonline.com/error?code=50076","suberror":"basic_action"}
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:27 char:9
+ $auth = Invoke-WebRequest "https://login.microsoftonline.com/$tenanti ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
ConvertFrom-Json : Cannot bind argument to parameter 'InputObject' because it is null.
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:29 char:19
+ $token = ($auth | ConvertFrom-Json).access_token
+                   ~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [ConvertFrom-Json], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

Invoke-WebRequest : {"error":{"code":"AuthenticationFailedMissingToken","message":"Authentication failed. The 'Authorization' header is missing the access token."}}
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:34 char:9
+ $data = Invoke-WebRequest "https://management.azure.com/subscriptions ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

当我使用在用户帐户上创建的应用程序密码更改密码时的输出

Invoke-WebRequest : {"error":"invalid_grant","error_description":"AADSTS50126: Invalid username or password.\r\nTrace ID: 3674934a-120b-48f3-96d8-7ec8ddf44300\r\nCorrelation ID: 
593aecd7-bbb2-4c5a-96e1-050bc00047ac\r\nTimestamp: 2019-10-02 13:26:46Z","error_codes":[50126],"timestamp":"2019-10-02 
13:26:46Z","trace_id":"3674934a-120b-48f3-96d8-7ec8ddf44300","correlation_id":"593aecd7-bbb2-4c5a-96e1-050bc00047ac","error_uri":"https://login.microsoftonline.com/error?code=50126"}
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:27 char:9
+ $auth = Invoke-WebRequest "https://login.microsoftonline.com/$tenanti ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
ConvertFrom-Json : Cannot bind argument to parameter 'InputObject' because it is null.
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:29 char:19
+ $token = ($auth | ConvertFrom-Json).access_token
+                   ~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [ConvertFrom-Json], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

Invoke-WebRequest : {"error":{"code":"AuthenticationFailedMissingToken","message":"Authentication failed. The 'Authorization' header is missing the access token."}}
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:34 char:9
+ $data = Invoke-WebRequest "https://management.azure.com/subscriptions ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
4

1 回答 1

2

据我所知,应用密码用于与不支持现代身份验证的客户端完成 MFA。现在,您使用 ROPC OAuth 流。APP密码不支持。

根据情况,我建议你手动完成MFA来获取刷新令牌,然后我们使用刷新令牌来获取访问令牌并调用API。因为 MFA 刷新令牌在您撤销之前不会过期。或者您使用OAuth 2.0 客户端凭据流来获取访问令牌。例如

用户刷新令牌

  1. 注册 Azure AD 应用程序

  2. 使用OAuth 2.0 授权码流完成 MFA 并获取刷新令牌

$Params = @{
    'client_id' = 'b0114608-677e-4eca-ae22-60c32e1782d9' 
    'redirect_URI' = 'https://www.baidu.com'
    'response_type'='code'
    'scope' = 'offline_access openid https://management.azure.com/user_impersonation'
}
$ClientSecret =''
$TeantID = ''
$Query = "?"; $Params.Keys | % {$Query+= "$($_)=$($Params.Item($_))&"} ; $Query = $Query.TrimEnd('&')


$IE= new-object -ComObject "InternetExplorer.Application"
$IE.Visible = $true
$IE.navigate2("https://login.microsoftonline.com/$($TeantID)/oauth2/v2.0/authorize$Query")

write-host "get authorization code"
pause

Add-Type -AssemblyName System.Web
[System.Web.HttpUtility]::ParseQueryString(([uri] $IE.LocationURL).Query)['code']
$Code = [System.Web.HttpUtility]::ParseQueryString(([uri] $IE.LocationURL).Query)['code']
$IE.Quit()

$TokenResult = Invoke-RestMethod -Method Post -ContentType 'application/x-www-form-urlencoded' -Uri "https://login.microsoftonline.com/$($TeantID)/oauth2/v2.0/token" -Body @{
    client_id     = $Params.client_id
    scope         = ''
    code          = $Code
    redirect_uri  = $Params.Redirect_URI
    grant_type    = 'authorization_code'
    client_secret = $ClientSecret
}

$TokenResult.refresh_token
  1. 获取访问令牌并调用 api
$TokenResult = Invoke-RestMethod -Method Post -ContentType 'application/x-www-form-urlencoded' -Uri "https://login.microsoftonline.com/$($TeantID)/oauth2/v2.0/token" -Body @{
    client_id     = ''
    scope         = 'https://management.azure.com/user_impersonation'
    redirect_uri  = ''
    grant_type    = 'refresh_token'
    client_secret = ''
    refresh_token =''
}



 Invoke-RestMethod -Method Get -Uri '' -Headers @{Authorization = "Bearer "+ $TokenResult.access_token}

使用 OAuth 2.0 客户端凭据流

$TokenResult = Invoke-RestMethod -Method Post -ContentType 'application/x-www-form-urlencoded' -Uri "https://login.microsoftonline.com/$($TeantID)/oauth2/v2.0/token" -Body @{
    client_id     = ''
    scope         = 'https://management.azure.com/.default'
    grant_type    = 'client_credentials'
    client_secret = ''

}

 Invoke-RestMethod -Method Get -Uri '' -Headers @{Authorization = "Bearer "+ $TokenResult.access_token}

更新根据您的需要,您可以创建服务主体并将 RABC 角色分配给服务主体。然后,您可以通过 OAuth 2.0 客户端凭据流获取访问令牌并调用 Azure rest api。详细步骤如下

  1. 创建服务主体并将 RABC 角色分配给服务主体
Connect-AzAccount
$password=''
$credentials = New-Object Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential -Property @{ StartDate=Get-Date; EndDate=Get-Date -Year 2024; Password=$password'}
$sp = New-AzAdServicePrincipal -DisplayName jimtest1 -PasswordCredential $credentials

New-AzRoleAssignment -ApplicationId $sp.ApplicationId -RoleDefinitionName Owner
  1. 获取访问令牌
# get access token
$TeantID='hanxia.onmicrosoft.com'
$TokenResult = Invoke-RestMethod -Method Post -ContentType 'application/x-www-form-urlencoded' -Uri "https://login.microsoftonline.com/$($TeantID)/oauth2/v2.0/token" -Body @{
    client_id     = $sp.ApplicationId # the application id of service principal
    scope         = 'https://management.azure.com/.default'
    grant_type    = 'client_credentials'
    client_secret = $password # you use it in step 1

}
  1. 调用 Azure Rest API
#list resource group
$values =Invoke-RestMethod -Method Get -Uri "https://management.azure.com/subscriptions/e5b0fcfa-e859-43f3-8d84-5e5fe29f4c68/resourcegroups?api-version=2019-05-10" -Headers @{
Authorization = "Bearer "+ $TokenResult.access_token
ContentType = 'application/json'
}

在此处输入图像描述

更多详情,请参阅

https://docs.microsoft.com/en-us/powershell/azure/create-azure-service-principal-azureps?view=azps-2.7.0

https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-api-authentication#get-app-only-access-token-for-azure-resource-manager

于 2019-10-03T02:00:38.560 回答