powershell - Azure ARM 访问令牌错误的受众
问题描述
我正在尝试从 Azure ARM 获取有关特定资源的信息。目前,我可以使用以下文章https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow从 oAuth2 获取访问令牌,但是当我尝试使用它时,我收到以下错误:
Invoke-RestMethod : {"error":{"code":"InvalidAuthenticationTokenAudience","message":"已为错误的受众或资源'00000002-0000-0000-c000-000000000000'获取访问令牌。它应该完全匹配与允许的受众之一'https://management.core.windows.net/'、'https://management.core.windows.net'、'https://management.azure.com/'、'https ://management.azure.com'。"}}
下面是我试图运行的代码:
param
(
[Parameter(Mandatory=$true)][System.String] $ResourceId,
[Parameter(Mandatory=$true)][System.String] $APIVersion
)
function Urls-Authorization
{
[OutputType([System.Uri])]
[CmdletBinding()]
param
(
[Parameter(Mandatory=$false)] [System.Guid] $TenantId
)
return [System.Uri]::new("https://login.microsoftonline.com/$($TenantId)/oauth2/token")
}
function Urls-Management
{
[OutputType([System.Uri])]
[CmdletBinding()]
param()
return [System.Uri]::new("https://management.azure.com")
}
function Urls-Resource
{
[OutputType([System.Uri])]
[CmdletBinding()]
param()
return [System.Uri]::new((Urls-Management), "$($ResourceId)?api-version=$($APIVersion)")
}
function ConvertFrom-SecureString
{
[OutputType([System.String])]
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)] [SecureString] $SecureString
)
return [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString))
}
function New-AccessToken
{
[OutputType([System.String])]
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)] [System.Uri] $ResourceUrl,
[Parameter(Mandatory=$true)] [System.Guid] $TenantId,
[Parameter(Mandatory=$true)] [System.Guid] $ClientId,
[Parameter(Mandatory=$true)] [SecureString] $Password,
[Parameter(Mandatory=$false)] [System.DateTime] $Expires = ($(Get-Date).AddMinutes(60).ToUniversalTime()),
[Parameter(Mandatory=$false)] [System.DateTime] $NotBefore = ([System.DateTime]::UtcNow)
)
#https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
$AuthorityUrl = Urls-Authorization -TenantId $TenantId
try
{
$RequestBody = [ordered]@{
'grant_type' = 'client_credentials';
'client_id' = $ClientId;
'scope ' = $ResourceUrl;
'client_secret' = "$(ConvertFrom-SecureString -SecureString $Password)";
}
$Response = Invoke-RestMethod -Uri $AuthorityUrl -Method Post -Body $RequestBody -ErrorAction Stop
}
catch
{
Write-Log -Type ERROR -Message "Token could not be acquired"
throw
}
return $Response.access_token
}
function Headers
{
[OutputType([Hashtable])]
[CmdletBinding()]
param
(
[Parameter(Mandatory=$false)] [System.String] $ContentType,
[Parameter(Mandatory=$true)] [System.String] $AccessToken
)
$Headers = @{}
if ($ContentType -ne $null) {$Headers.Add("Content-Type", $ContentType)}
$Headers.Add("Authorization", "Bearer $($AccessToken)")
return $Headers
}
Invoke-RestMethod -Method Get -Uri (Urls-Resource) -Headers (Headers -ContentType "application/json" -AccessToken (New-AccessToken -ResourceUrl (Urls-Management) -TenantId $env:AZURE_TENANT_ID -ClientId $env:AZURE_CLIENT_ID -Password (ConvertTo-SecureString -String $env:AZURE_CLIENT_SECRET -AsPlainText -Force))) | ConvertFrom-Json
正如我之前提到的,我使用New-AccessToken函数获取访问令牌。我什至尝试以下,我得到同样的错误:
- 将 New-AccessToken 中的 ResourceUrl 参数从 Urls-Management 更改为 Urls-Resource
- 将 /.default 添加到 Urls-管理地址
- 将更改 Urls-Management 从https://management.azure.com添加到https://management.azure.com/
你知道会发生什么吗?关于我应该如何面对这个错误的任何想法?
解决方案
我认为这个错误提供了一些很好的见解。我会New-AccessToken
改为:
function New-AccessToken
{
[OutputType([System.String])]
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)] [System.Uri] $ResourceUrl,
[Parameter(Mandatory=$true)] [System.Guid] $TenantId,
[Parameter(Mandatory=$true)] [System.Guid] $ClientId,
[Parameter(Mandatory=$true)] [SecureString] $Password,
[Parameter(Mandatory=$false)] [System.DateTime] $Expires = ($(Get-Date).AddMinutes(60).ToUniversalTime()),
[Parameter(Mandatory=$false)] [System.DateTime] $NotBefore = ([System.DateTime]::UtcNow)
)
#https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
$AuthorityUrl = Urls-Authorization -TenantId $TenantId
try
{
$RequestBody = [ordered]@{
'grant_type' = 'client_credentials';
'client_id' = $ClientId;
'scope ' = $ResourceUrl;
'client_secret' = "$(ConvertFrom-SecureString -SecureString $Password)";
'resource' = 'https://management.azure.com/';
}
$Response = Invoke-RestMethod -Uri $AuthorityUrl -Method Post -Body $RequestBody -ErrorAction Stop
}
catch
{
Write-Log -Type ERROR -Message "Token could not be acquired"
throw
}
return $Response.access_token
}
基本上,添加'resource' = 'https://management.azure.com/';
. $RequestBody
我在这个存储库中有几个 Azure Rest 调用,但它在 groovy 中(尽管这应该不是问题)。
此外,您是否考虑过使用Az模块?它在后台实现所有其余逻辑,并提供与 Azure 资源通信的即用型 cmdlet。
推荐阅读
- java - 带/不带baseObservable的android viewmodel
- scala - Scala / Joda - Joda DateTimeFormat 不适用
- c# - C# Concat 数组中的两个字符
- sql - 需要帮助以 2 个不同的条件从 1 个表中加入 2 个选择查询
- google-bigquery - 在将 Google BigQuery 作为源数据库的 Metabase 中使用字段过滤器时出现无法识别的名称
- java - Lombok SuperBuilder 继承
- python - Scrapy 无法从网站上抓取电子邮件字段
- html - 带有无包装子元素的 Flex 子元素溢出屏幕
- python - 通过集成 PDF 获得的错误累积分布
- c - 修改结构实例的变量