【问题标题】:Azure Automation script to request OMS用于请求 OMS 的 Azure 自动化脚本
【发布时间】:2017-07-21 17:44:41
【问题描述】:

我在 PowerShell 中编写了一个自动化脚本,它每天早上都会给我一份关于我们的 azure 订阅(虚拟机、自动化作业、警报等)的报告。 现在,我正在添加一个新功能,该功能在我的计算机上运行良好,但在从自动化运行时失败,我不知道如何使它工作。

在我的电脑上运行良好(VS code / PS 5.1 / PS 4.0)

$omsRGname = "xxx"
$omsWorkspaceName = "xxx"
$omsQueryThreat = 'Type=ProtectionStatus ThreatStatusRank!=150 ThreatStatusRank!=470 | select Computer,Threat,ThreatStatus'
$ArrayThreat = New-Object System.Collections.ArrayList

function OmsRequest {
    Param(
        [parameter(Position = 0, Mandatory = $true)]
        $omsRG,
        [parameter(Position = 1, Mandatory = $true)]
        $omsWorkspace,
        [parameter(Position = 2, Mandatory = $true)]
        $omsQuery
    )
    Process {
        Import-Module AzureRm.OperationalInsights
        $error.clear()
        $Result.clear
        $script:Result = Get-AzureRmOperationalInsightsSearchResults -ResourceGroupName $omsRG -WorkspaceName $omsWorkspace -Query $omsQuery
        $reqIdParts = $Result.Id.Split("/")
        $reqId = $reqIdParts[$reqIdParts.Count - 1]
        $wait = Get-Date
        while ($Result.Metadata.Status -eq "Pending" -and $error.Count -eq 0) {
            $Result = Get-AzureRmOperationalInsightsSearchResults -WorkspaceName $omsWorkspace -ResourceGroupName $omsRG -Id $reqId
            #debug
            $elapsedTime = $(get-date) - $wait
            Write-Output "Elapsed: $elapsedTime -- Status: $($Result.Metadata.Status)"
            Write-Output "Count: $($Result.Count)"
        }
    }
}

OmsRequest $omsRGname $omsWorkspaceName $omsQueryThreat
#debug
Write-Output "VALUEOUT:" $Result.Value
#
$OMSComputers = $Result.Value | ConvertFrom-Json
if ($OMSComputers) {
    foreach ( $ThreatDetails in $OMSComputers) {
        <#write "$(get-date($ThreatDetails.__metadata.TimeGenerated) -format G) - $($ThreatDetails.Computer) - $($ThreatDetails.Threat) - $($ThreatDetails.ThreatStatus)"#>
        $ThDetails = [PSCustomObject] @{
            Date         = (get-date($ThreatDetails.__metadata.TimeGenerated) -format G);
            Computer     = $ThreatDetails.Computer;
            Threat       = $ThreatDetails.Threat;
            ThreatStatus = $ThreatDetails.ThreatStatus;
        }
        $ArrayThreat.Add($ThDetails) |Out-Null
    }
}
else {Write-Output "OK"}

$ArrayThreat

从我的本地计算机

Elapsed: 00:00:00.4270000 -- Status: Successful
Count: 1

Date                Computer      Threat                   ThreatStatus
----                --------      ------                   ------------
29/06/2017 12:55:37 xxx.local     Virus:ALisp/Bursted.DT   Quarantined
29/06/2017 11:48:28 xxx.local     Virus:ALisp/Bursted.DT   Quarantined
29/06/2017 10:55:37 xxx.local     Virus:ALisp/Bursted.DT   Quarantined
29/06/2017 09:55:38 xxx.local     Virus:ALisp/Bursted.DT   Quarantined
29/06/2017 08:48:28 xxx.local     Virus:ALisp/Bursted.DT   Quarantined
29/06/2017 08:48:28 xxx.local     Virus:ALisp/Bursted.DT   Quarantined
29/06/2017 07:55:37 xxx.local     Virus:ALisp/Bursted.DT   Quarantined
29/06/2017 07:55:37 xxx.local     Virus:ALisp/Bursted.DT   Quarantined
29/06/2017 06:48:28 xxx.local     Virus:ALisp/Bursted.DT   Quarantined
29/06/2017 06:48:28 xxx.local     Virus:ALisp/Bursted.DT   Quarantined

当我从自动化运行我的代码时,我得到了这个错误

ConvertFrom-Json : The input object cannot be bound to any parameters for the command either because the command does 
not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
At line:164 char:33
+ $OMSComputers = $Result.Value | ConvertFrom-Json
+                                 ~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: ({
  "Computer"...ng": {}
  }
}:JObject) [ConvertFrom-Json], ParameterBindingException
    + FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

好吧,我的错误就在这里

$OMSComputers = $Result.Value | ConvertFrom-Json

当我查看它的值时,我得到了这个(只是从 $Result.Value 给出的列表中获取了一个属性)

VALUEOUT:

Name                       : Computer
Type                       : Property
HasValues                  : True
First                      : {}
Last                       : {}
Count                      : 1
Parent                     : {Computer, Threat, ThreatStatus, __metadata}
Root                       : {Computer, Threat, ThreatStatus, __metadata}
Next                       : {}
Previous                   : 
Path                       : Computer
LineNumber                 : 0
LinePosition               : 0
IsReadOnly                 : False
AllowNew                   : True
AllowEdit                  : True
AllowRemove                : True
SupportsChangeNotification : True
SupportsSearching          : False
SupportsSorting            : False
IsSorted                   : False
SortProperty               : 
SortDirection              : Ascending
IsFixedSize                : False
SyncRoot                   : System.Object
IsSynchronized             : False

看到这条线

Keys                       : {Computer, Threat, ThreatStatus, __metadata}

我尝试将其解析为哈希表,但没有结果。

有没有人有其他创造性的方法来解决这个问题? 谢谢

编辑: 我只是在这里完成了我的职能。但是在完整的脚本中,我连接良好并且 PS 模块已经存在(如果不是功能失败告诉我,则无法找到 RG,但尽管如此,我单击并从您的链接添加模块)。 如果我查看 $result 内容,我会得到查询结果。

{
    "Computer": "xxx.local",
    "Threat": "Virus:ALisp/Bursted.DT",
    "ThreatStatus": "Quarantined",
    "__metadata": {
        "Type": "ProtectionStatus",
        "TimeGenerated": "2017-06-29T10:55:37.77Z",
        "highlighting": {}
    }
}

当我询问它的类型时

Newtonsoft.Json.Linq.JObject

所以我导入 Newtonsoft.Json 模块并尝试从这种 Json 转换,但它也失败了。

看起来我的 OMS 查询正在运行(我在 $Result 中有一个结果),但是当自动化尝试使用“ConvertFrom-Json”进行转换时,它失败了。

#debug
Write-Output "VALUEOUT:"
Write-Output "Get-variable RESULT"
Get-Variable Result -ValueOnly |format-list
$OMSComputers = $Result.Value | ConvertFrom-Json

输出:

    VALUEOUT:
    Get-variable RESULT

    Id       : subscriptions/xxx/providers/Microsoft.Operatio
               nalInsights/workspaces/xxx/search/xxx|10.1.0.27|2017-07-05T14-33-52Z
    Metadata : Microsoft.Azure.Commands.OperationalInsights.Models.PSSearchMetadata
    Error    : 
    Value    : {"Computer": "xxx.local" "Threat": "Virus:ALisp/Bursted.DT" "ThreatStatus": "Quarantined" 
               "__metadata": {
                 "Type": "ProtectionStatus",
                 "TimeGenerated": "2017-06-29T10:55:37.77Z",
                 "highlighting": {}
               }, "Computer": "xxx.local" "Threat": "Virus:ALisp/Bursted.DT" "ThreatStatus": "Quarantined" 
               "__metadata": {
                 "Type": "ProtectionStatus",
                 "TimeGenerated": "2017-06-29T09:48:28.42Z",
                 "highlighting": {}
               }, "Computer": "xxx.local" "Threat": "Virus:ALisp/Bursted.DT" "ThreatStatus": "Quarantined" 
               "__metadata": {
                 "Type": "ProtectionStatus",
                 "TimeGenerated": "2017-06-29T08:55:37.757Z",
                 "highlighting": {}
               }, "Computer": "xxx.local" "Threat": "Virus:ALisp/Bursted.DT" "ThreatStatus": "Quarantined" 
               "__metadata": {
                 "Type": "ProtectionStatus",
                 "TimeGenerated": "2017-06-29T07:55:38.327Z",
                 "highlighting": {}
               }...}

ConvertFrom-Json : The input object cannot be bound to any parameters for the command either because the command does 

not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

At line:65 char:33

+ $OMSComputers = $Result.Value | ConvertFrom-Json

+                                 ~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: ({

  "Computer"...ng": {}

  }

}:JObject) [ConvertFrom-Json], ParameterBindingException

    + FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

我不明白为什么 ConvertFrom-Json 失败:/

【问题讨论】:

    标签: azure visual-studio-code azure-powershell azure-automation


    【解决方案1】:

    在 Azure 自动化账户中,不支持使用Import-Module AzureRm.OperationalInsights 导入模块。您的错误根本原因是 $script:Result 为空。您需要将 AzureRm.OperationalInsights 导入您的 Azure 自动化帐户。请参考以下步骤:

    1.打开link

    2.点击Deploy to Azure Automation

    3.在你的运行手册中删除Import-Module AzureRm.OperationalInsights

    注意:执行Get-AzureRmOperationalInsightsSearchResults时,需要在runbook中登录Azure,根据你的runbook,好像没有这一步。如果您不这样做,请将其添加到您的 Runbook。

    以下 Runbook 适合我。

    $connectionName = "AzureRunAsConnection"
    try
    {
        # Get the connection "AzureRunAsConnection "
        $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName         
    
        "Logging in to Azure..."
        Add-AzureRmAccount `
            -ServicePrincipal `
            -TenantId $servicePrincipalConnection.TenantId `
            -ApplicationId $servicePrincipalConnection.ApplicationId `
            -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
    }
    catch {
        if (!$servicePrincipalConnection)
        {
            $ErrorMessage = "Connection $connectionName not found."
            throw $ErrorMessage
        } else{
            Write-Error -Message $_.Exception
            throw $_.Exception
        }
    }
    
    ##
    $omsRGname = "shuivm"
    $omsWorkspaceName = "shuitest"
    $omsQueryThreat = 'Type=ProtectionStatus ThreatStatusRank!=150 ThreatStatusRank!=470 | select Computer,Threat,ThreatStatus'
    $ArrayThreat = New-Object System.Collections.ArrayList
    
    function OmsRequest {
        Param(
            [parameter(Position = 0, Mandatory = $true)]
            $omsRG,
            [parameter(Position = 1, Mandatory = $true)]
            $omsWorkspace,
            [parameter(Position = 2, Mandatory = $true)]
            $omsQuery
        )
        Process {
    
            $error.clear()
            $Result.clear
            $script:Result = Get-AzureRmOperationalInsightsSearchResults -ResourceGroupName $omsRG -WorkspaceName $omsWorkspace -Query $omsQuery
            $reqIdParts = $Result.Id.Split("/")
            $reqId = $reqIdParts[$reqIdParts.Count - 1]
            $wait = Get-Date
            while ($Result.Metadata.Status -eq "Pending" -and $error.Count -eq 0) {
                $Result = Get-AzureRmOperationalInsightsSearchResults -WorkspaceName $omsWorkspace -ResourceGroupName $omsRG -Id $reqId
                #debug
                $elapsedTime = $(get-date) - $wait
                Write-Output "Elapsed: $elapsedTime -- Status: $($Result.Metadata.Status)"
                Write-Output "Count: $($Result.Count)"
            }
        }
    }
    
    OmsRequest $omsRGname $omsWorkspaceName $omsQueryThreat
    #debug
    Write-Output "VALUEOUT:" $Result.Value
    #
    $OMSComputers = $Result.Value | ConvertFrom-Json
    if ($OMSComputers) {
        foreach ( $ThreatDetails in $OMSComputers) {
            <#write "$(get-date($ThreatDetails.__metadata.TimeGenerated) -format G) - $($ThreatDetails.Computer) - $($ThreatDetails.Threat) - $($ThreatDetails.ThreatStatus)"#>
            $ThDetails = [PSCustomObject] @{
                Date         = (get-date($ThreatDetails.__metadata.TimeGenerated) -format G);
                Computer     = $ThreatDetails.Computer;
                Threat       = $ThreatDetails.Threat;
                ThreatStatus = $ThreatDetails.ThreatStatus;
            }
            $ArrayThreat.Add($ThDetails) |Out-Null
        }
    }
    else {Write-Output "OK"}
    
    $ArrayThreat
    

    【讨论】:

    • 嗨,刚刚尝试了您的代码,我遇到了与“| ConvertFrom-Json”相同的错误。我编辑了第一篇文章。
    • @Folk 我检查了$Result.Value 不是json 格式,它是一种文本格式。你想转换成json吗?如果是。你应该使用$Result.Value|ConvertTo-JsonConvertTo-Json 将文件转换为 json 格式。如果不是,您当地的 Power Shell 上的$Result.Value 的结果是什么。是Json 格式吗?如果你只想使用文本格式,我认为你不需要使用ConvertFrom-Json
    【解决方案2】:

    我对命令有完全相同的问题: $Result.Value | ConvertFrom-Json

    这种行为既发生在自动化运行手册中,也发生在本地执行

    这是我使用 ForEach 从查询中提取 $result.Value 并将值传递给哈希表的解决方法:

      $dynamicQuery = "* | measure count() by Type"
    $now = Get-Date
    $StartDateAndTime = $now.AddHours(-24).ToString("yyyy-MM-ddTHH:mm:ss")
    
    $EndDateAndTime = $now.ToString("yyyy-MM-ddTHH:mm:ss")
    
    $result = Get-AzureRmOperationalInsightsSearchResults `
    -ResourceGroupName $ResourceGroupName `
    -WorkspaceName $WorkSpaceName `
    -Query $dynamicQuery `
    -Start $StartDateAndTime `
    -End $EndDateAndTime 
    
     $queryResults = new-object System.Collections.Hashtable
    
    Foreach ($item in $result.value)
    {
     $obj1 = $item["Type"].ToString()
       $obj2= $item["AggregatedValue"].ToString()
      [void]$queryResults.Add($obj1,$obj2)
    }
    
    Write-Output $queryResults
    

    我已在此处将其作为问题添加,因为这不是模块的记录方式,也不是一个优雅的解决方案: https://github.com/Azure/azure-powershell/issues/4256

    【讨论】:

    • 嗨,它可以在我的电脑上运行 (win7 - PS5.1/4.0) [$OMSComputers = $Result.Value | ConvertFrom-Json],但无法进入自动化。我在我的第一篇文章中显示了我的计算机的结果。我会试试你的解决方案,谢谢。
    • 嗨@Folk - 这是 AzureRM.Operational.Insights 3.2.0 的一个错误 测试确认 3.0.1 将在 $result.Value 中返回正确的 JSON 不幸的是,似乎没有上传这个旧版本模块到 Azure,它总是在“提取活动”上失败
    【解决方案3】:

    感谢您的所有帮助:)

    这是我在模块损坏时使用的调试代码(并且已经添加到我们的生产 MorningReport 脚本中)

    ###Query OMS for malware state
    #MorningMalwareDebug region Authentication
    Write-Verbose ""
    Write-Verbose "------------------------ Authentication ------------------------"
    Write-Verbose "Logging in to Azure ..."
    try {
        $connectionName = "AzureRunAsConnection"
        # Get the connection "AzureRunAsConnection "
        $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName         
        $null = Add-AzureRmAccount `
            -ServicePrincipal `
            -TenantId $servicePrincipalConnection.TenantId `
            -ApplicationId $servicePrincipalConnection.ApplicationId `
            -SubscriptionName "xxxx" `
            -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
    
        Write-Verbose "Successfully logged in to Azure." 
    } 
    catch {
        if (!$servicePrincipalConnection) {
            $ErrorMessage = "Connection $connectionName not found."
            throw $ErrorMessage
        } 
        else {
            Write-Error -Message $_.Exception
            throw $_.Exception
        }
    }
    #MorningMalwareDebug endregion Authentication
    ####
    #MorningMalwareDebug region Function
    function OmsRequest {
        Param(
            [parameter(Position = 0, Mandatory = $true)]
            $omsRG,
            [parameter(Position = 1, Mandatory = $true)]
            $omsWorkspace,
            [parameter(Position = 2, Mandatory = $true)]
            $omsQuery
        )
        Process {
            Import-Module AzureRm.OperationalInsights
            $error.clear()
            $Result.clear
            $script:Result = Get-AzureRmOperationalInsightsSearchResults -ResourceGroupName $omsRG -WorkspaceName $omsWorkspace -Query $omsQuery -Start $FromStartDate -End $ToEndDate
            $reqIdParts = $Result.Id.Split("/")
            $reqId = $reqIdParts[$reqIdParts.Count - 1]
            $wait = Get-Date
            while ($Result.Metadata.Status -eq "Pending" -and $error.Count -eq 0) {
                $Result = Get-AzureRmOperationalInsightsSearchResults -WorkspaceName $omsWorkspace -ResourceGroupName $omsRG -Id $reqId
                $elapsedTime = $(get-date) - $wait
                Write-Output "Elapsed:" $elapsedTime "-- Status:" $Result.Metadata.Status
            }
        }
    }
    #MorningMalwareDebug endregion Function
    ####
    #MorningMalwareDebug region Variables
    $now = Get-Date
    $FromStartDate = $now.AddHours(-24).ToString("yyyy-MM-ddTHH:mm:ss")
    $ToEndDate = $now.ToString("yyyy-MM-ddTHH:mm:ss")
    $omsRGname = "xxxx"
    $omsWorkspaceName = "xxxx"
    $omsQueryThreat = 'Type=ProtectionStatus ThreatStatusRank!=150 ThreatStatusRank!=470 | select Computer,Threat,ThreatStatus'
    $ArrayThreat = New-Object System.Collections.ArrayList
    #MorningMalwareDebug endregion Variables
    ####
    #MorningMalwareDebug region Main
    OmsRequest $omsRGname $omsWorkspaceName $omsQueryThreat
    if ($Result.value) {
        $ArrayThreat.clear()
        Foreach ($ThreatDetails in $Result.value) {
            $ThDetails = [PSCustomObject] @{
                Computer     = ($ThreatDetails["Computer"].ToString()).split('.')[0];
                Threat       = $ThreatDetails["Threat"].ToString();
                ThreatStatus = $ThreatDetails["ThreatStatus"].ToString();
            }
            $ArrayThreat.Add($ThDetails)
        }
        Write-Output $ArrayThreat
    }
    else {write-output "Pas de menace"}
    #MorningMalwareDebug endregion Main
    ####
    #MorningMalwareDebug region BuildMail
    #MorningMalwareDebug endregion BuildMail
    ####
    #MorningMalwareDebug region SendMail
    #MorningMalwareDebug endregion SendMail
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      • 1970-01-01
      • 2021-10-29
      • 2018-08-18
      • 1970-01-01
      • 1970-01-01
      • 2020-06-02
      相关资源
      最近更新 更多