用于请求OMS的Azure自动化脚本

时间:2017-07-04 13:38:57

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

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

在我的电脑上运行良好(VS代码/ 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

当我从Automation运行我的代码时,我收到此错误

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

isee this line

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)但是当Automation尝试使用'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失败了:/

3 个答案:

答案 0 :(得分:0)

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

1.打开link

2.点击Deploy to Azure Automation

3.删除Runbook中的Import-Module AzureRm.OperationalInsights

注意:当您执行Get-AzureRmOperationalInsightsSearchResults时,您需要在Runbook中登录Azure,根据您的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

答案 1 :(得分:0)

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

此行为在自动化Runbook和本地执行

中都会发生

这是我的解决方法,使用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

答案 2 :(得分:0)

感谢您的帮助:)

这是我使用过的调试代码(已经添加到我们的生产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