【问题标题】:Azure PowerShell runbook: -InFile flag of Invoke-RestMethod not working as intendedAzure PowerShell runbook:Invoke-RestMethod 的 -InFile 标志未按预期工作
【发布时间】:2021-06-13 01:33:17
【问题描述】:

我正在创建一个 Azure Runbook 脚本,用于获取图像,然后通过 http 再次发送它以更新特定公司用户的个人资料图片。相关文档说,运行 runbook 的工作人员有一个可访问的临时存储,确实我可以在那里看到文件下载,但是当通过 -InFile 指定其路径时,它不断返回 400 并且在邮递员上它工作得很好,所以通过我自己计算机的 PowerShell 在本地执行。代码如下:

## Begin fetching auth2.0 token ##

## Fetch user

$boundary = [System.Guid]::NewGuid().ToString(); 
$LF = "`r`n";

# Because the workers run an earlier version of PowerShell I had to declare the form in this 
jibberish way, as per another stackoverflow thread. However this works and the auth2.0 is retrieved.

$bodyLines = ( 
    "--$boundary",
    "Content-Disposition: form-data; name=`"grant_type`"$LF",
    "client_credentials$LF",
    "--$boundary",
    "Content-Disposition: form-data; name=`"client_id`"$LF",
    "[client_id]$LF",
    "--$boundary",
    "Content-Disposition: form-data; name=`"scope`"$LF",
    "https://graph.microsoft.com/.default$LF",
    "--$boundary",
    "Content-Disposition: form-data; name=`"client_secret`"$LF",
    "[client_secret]$LF",
    "--$boundary--$LF" 
) -join $LF

$AuthTokenRequestHeaders = @{
    "Cache-Control" = "no-cache"
}

$AuthTokenResponse = Invoke-RestMethod 'https://login.microsoftonline.com/[company-name].onmicrosoft.com/oauth2/v2.0/token' -Method 'POST' -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines -Headers $AuthTokenRequestHeaders

$authToken = $AuthTokenResponse.access_token

#### Finish token fetching ####


# Get user-specific Microsoft Object ID
$MsolCred = Get-AutomationPSCredential -Name "Office365"
Connect-MsolService -Credential $MsolCred -AzureEnvironment "AzureCloud"
$MsolUserId = (Get-MsolUser -UserPrincipalName $Email).ObjectId.Guid


#### Begin updating profile picture ####
$RequestHeader = @{
    "Authorization" = "Bearer $authToken"
    "Content-Type" = "image/jpeg"
}

# Look at contents on static OneDrive folder
$OneDriveFolderContents = (Invoke-RestMethod -Uri 'https://graph.microsoft.com/v1.0/drives/[drive-id]/items/[folder-id]/children' -Method Get -Headers $RequestHeader)

# Logic to look for the most recent file
$MostRecentFileDate = 0;
$MostRecentFileId = "";

foreach ($file in $OneDriveFolderContents.value) {

    if ($file.createdDateTime -gt $MostRecentFileDate) {
        $MostRecentFileDate = $file.createdDateTime
        $MostRecentFileId = $file.id
    }

}

# GET for most recent image
$restById = (Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/drives/[drive-id]/items/$mostRecentFileId/content" -Method Get -Headers $RequestHeader -OutFile "profilepicture.jpeg") 


# This section was for debugging purposes. Checking if the file was downloaded correctly and its path in the runbook worker who's running the script. Because workers only have one randomly named folder and a folder named "diags" I just exclude the diags folder and look for it inside the temporary folder after finding its name
$var1 =  (Get-ChildItem -Path 'C:\Temp\' -Depth 2).Directory
$var2 = ""

foreach ($folder in $var1) {

    if ($folder.Name -ne "diags") {
        $var2 = $folder.Name
    }
    
}

Write-Output "Found folder named $var2 to use in path"

## End debugging section


$forinfile = "C:\Temp\$var2\profilepicture.jpeg"

# This confirms that the file is indeed there
Write-Output (Get-ChildItem -Path C:\Temp\ -Depth 2)

# PUT most recent image to the specific user
$userUrlString = "https://graph.microsoft.com/v1.0/users/" + $MsolUserId + '/photo/$value'

# This is the specific Invoke-RestMethod that returns a 400. Following are 4 different ones I tried with no success
Invoke-RestMethod -Uri $userUrlString -Method Put -Headers $RequestHeader -InFile "$forinfile"
Invoke-RestMethod -Uri $userUrlString -Method Patch -Headers $RequestHeader -InFile "profilepicture.jpeg"
Invoke-RestMethod -Uri $userUrlString -Method Put -Headers $RequestHeader -InFile "profilepicture.jpeg"
Invoke-RestMethod -Uri $userUrlString -Method Patch -Headers $RequestHeader -InFile "$forinfile"

该代码在我自己的机器上完美运行,但在 Azure 上它一直返回相同的错误:

以下是过去运行的一些额外调试输出,可确认文件存在:

回答我认为可能首先想知道的问题:在 Azure AD 上,auth2.0 令牌及其各自的应用程序已配置为允许代表其他人更新个人资料图片。在我自己的机器上,我可以在本地更改同事的照片。

【问题讨论】:

    标签: azure powershell microsoft-graph-api


    【解决方案1】:

    我使用你的脚本,它在我这边的 Azure 自动化运行手册中运行良好。

    由于 jpeg 文件已成功下载,问题应该出在最后一次 Graph 调用上。

    要解决此问题,您不需要使用:

    $MsolCred = Get-AutomationPSCredential -Name "Office365"
    Connect-MsolService -Credential $MsolCred -AzureEnvironment "AzureCloud"
    $MsolUserId = (Get-MsolUser -UserPrincipalName $Email).ObjectId.Guid
    $userUrlString = "https://graph.microsoft.com/v1.0/users/" + $MsolUserId + '/photo/$value'
    

    直接使用$userUrlString = "https://graph.microsoft.com/v1.0/users/" + $Email + '/photo/$value'即可。

    让我知道它是否有效。

    【讨论】:

    • 谢谢艾伦,我同时发现了这个问题。显然,这是 Azure 上使用的模块版本的问题。更新到最新版本后,一切运行完美
    • @Ress 很高兴知道这个问题已经解决:)
    猜你喜欢
    • 2018-08-15
    • 2015-06-06
    • 2021-11-28
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 2018-10-17
    相关资源
    最近更新 更多