Leggere i log dei flussi

Questo articolo illustra come leggere in modo selettivo parti dei log dei flussi di Azure Network Watcher usando PowerShell senza dover analizzare l'intero log. I log dei flussi vengono archiviati in un account di archiviazione in BLOB in blocchi. Ogni log è un BLOB in blocchi separato generato ogni ora e aggiornato con i dati più recenti ogni pochi minuti. Usando lo script fornito in questo articolo, è possibile leggere i dati più recenti dai log del flusso senza dover scaricare l'intero log.

I concetti illustrati in questo articolo non sono limitati a PowerShell e sono applicabili a tutte le lingue supportate dalle API Archiviazione di Azure.

Prerequisiti

Recuperare l'elenco di blocchi

Lo script di PowerShell seguente configura le variabili necessarie per eseguire query sul BLOB del log del flusso del gruppo di sicurezza di rete ed elencare i blocchi all'interno del BLOB in blocchi CloudBlockBlob . Aggiornare lo script in modo che contenga i valori validi per l'ambiente.

function Get-NSGFlowLogCloudBlockBlob {
    [CmdletBinding()]
    param (
        [string] [Parameter(Mandatory=$true)] $subscriptionId,
        [string] [Parameter(Mandatory=$true)] $NSGResourceGroupName,
        [string] [Parameter(Mandatory=$true)] $NSGName,
        [string] [Parameter(Mandatory=$true)] $storageAccountName,
        [string] [Parameter(Mandatory=$true)] $storageAccountResourceGroup,
        [string] [Parameter(Mandatory=$true)] $macAddress,
        [datetime] [Parameter(Mandatory=$true)] $logTime
    )

    process {
        # Retrieve the primary storage account key to access the network security group logs
        $StorageAccountKey = (Get-AzStorageAccountKey -ResourceGroupName $storageAccountResourceGroup -Name $storageAccountName).Value[0]

        # Setup a new storage context to be used to query the logs
        $ctx = New-AzStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey

        # Container name used by network security group flow logs
        $ContainerName = "insights-logs-networksecuritygroupflowevent"

        # Name of the blob that contains the network security group flow log
        $BlobName = "resourceId=/SUBSCRIPTIONS/${subscriptionId}/RESOURCEGROUPS/${NSGResourceGroupName}/PROVIDERS/MICROSOFT.NETWORK/NETWORKSECURITYGROUPS/${NSGName}/y=$($logTime.Year)/m=$(($logTime).ToString("MM"))/d=$(($logTime).ToString("dd"))/h=$(($logTime).ToString("HH"))/m=00/macAddress=$($macAddress)/PT1H.json"

        # Gets the storage blog
        $Blob = Get-AzStorageBlob -Context $ctx -Container $ContainerName -Blob $BlobName

        # Gets the block blog of type 'Microsoft.Azure.Storage.Blob.CloudBlob' from the storage blob
        $CloudBlockBlob = [Microsoft.Azure.Storage.Blob.CloudBlockBlob] $Blob.ICloudBlob

        #Return the Cloud Block Blob
        $CloudBlockBlob
    }
}

function Get-NSGFlowLogBlockList  {
    [CmdletBinding()]
    param (
        [Microsoft.Azure.Storage.Blob.CloudBlockBlob] [Parameter(Mandatory=$true)] $CloudBlockBlob
    )
    process {
        # Stores the block list in a variable from the block blob.
        $blockList = $CloudBlockBlob.DownloadBlockListAsync()

        # Return the Block List
        $blockList
    }
}


$CloudBlockBlob = Get-NSGFlowLogCloudBlockBlob -subscriptionId "yourSubscriptionId" -NSGResourceGroupName "FLOWLOGSVALIDATIONWESTCENTRALUS" -NSGName "V2VALIDATIONVM-NSG" -storageAccountName "yourStorageAccountName" -storageAccountResourceGroup "ml-rg" -macAddress "000D3AF87856" -logTime "11/11/2018 03:00" 

$blockList = Get-NSGFlowLogBlockList -CloudBlockBlob $CloudBlockBlob

La variabile $blockList restituisce un elenco di blocchi nel BLOB. Ogni BLOB in blocchi contiene almeno due blocchi. Il primo blocco ha una lunghezza di 12 byte e contiene le parentesi di apertura del log JSON. L'altro blocco è costituito dalle parentesi quadre di chiusura e ha una lunghezza di 2 byte. Nel log di esempio seguente sono presenti sette voci singole. Tutte le nuove voci nel log vengono aggiunte alla fine subito prima del blocco finale.

Name                                         Length Committed
----                                         ------ ---------
ZDk5MTk5N2FkNGE0MmY5MTk5ZWViYjA0YmZhODRhYzY=     12      True
NzQxNDA5MTRhNDUzMGI2M2Y1MDMyOWZlN2QwNDZiYzQ=   2685      True
ODdjM2UyMWY3NzFhZTU3MmVlMmU5MDNlOWEwNWE3YWY=   2586      True
ZDU2MjA3OGQ2ZDU3MjczMWQ4MTRmYWNhYjAzOGJkMTg=   2688      True
ZmM3ZWJjMGQ0ZDA1ODJlOWMyODhlOWE3MDI1MGJhMTc=   2775      True
ZGVkYTc4MzQzNjEyMzlmZWE5MmRiNjc1OWE5OTc0OTQ=   2676      True
ZmY2MjUzYTIwYWIyOGU1OTA2ZDY1OWYzNmY2NmU4ZTY=   2777      True
Mzk1YzQwM2U0ZWY1ZDRhOWFlMTNhYjQ3OGVhYmUzNjk=   2675      True
ZjAyZTliYWE3OTI1YWZmYjFmMWI0MjJhNzMxZTI4MDM=      2      True

Leggere il BLOB in blocchi

In questa sezione si legge la $blocklist variabile per recuperare i dati. Nell'esempio seguente viene eseguita l'iterazione dell'elenco di blocchi per leggere i byte da ogni blocco e archiviarli in una matrice. Per recuperare i dati usare il metodo DownloadRangeToByteArray.

function Get-NSGFlowLogReadBlock  {
    [CmdletBinding()]
    param (
        [System.Array] [Parameter(Mandatory=$true)] $blockList,
        [Microsoft.Azure.Storage.Blob.CloudBlockBlob] [Parameter(Mandatory=$true)] $CloudBlockBlob

    )
    # Set the size of the byte array to the largest block
    $maxvalue = ($blocklist | measure Length -Maximum).Maximum

    # Create an array to store values in
    $valuearray = @()

    # Define the starting index to track the current block being read
    $index = 0

    # Loop through each block in the block list
    for($i=0; $i -lt $blocklist.count; $i++)
    {
        # Create a byte array object to story the bytes from the block
        $downloadArray = New-Object -TypeName byte[] -ArgumentList $maxvalue

        # Download the data into the ByteArray, starting with the current index, for the number of bytes in the current block. Index is increased by 3 when reading to remove preceding comma.
        $CloudBlockBlob.DownloadRangeToByteArray($downloadArray,0,$index, $($blockList[$i].Length)) | Out-Null

        # Increment the index by adding the current block length to the previous index
        $index = $index + $blockList[$i].Length

        # Retrieve the string from the byte array

        $value = [System.Text.Encoding]::ASCII.GetString($downloadArray)

        # Add the log entry to the value array
        $valuearray += $value
    }
    #Return the Array
    $valuearray
}
$valuearray = Get-NSGFlowLogReadBlock -blockList $blockList -CloudBlockBlob $CloudBlockBlob

La $valuearray matrice contiene ora il valore stringa di ogni blocco. Per verificare la voce, ottenere dal secondo all'ultimo valore dalla matrice eseguendo $valuearray[$valuearray.Length-2]. Non è necessario l'ultimo valore perché è la parentesi chiusa.

Nell'esempio seguente vengono visualizzati i risultati di questo valore:

{
	"records": [
		{
			"time": "2017-06-16T20:59:43.7340000Z",
			"systemId": "abcdef01-2345-6789-0abc-def012345678",
			"category": "NetworkSecurityGroupFlowEvent",
			"resourceId": "/SUBSCRIPTIONS/00000000-0000-0000-0000-000000000000/RESOURCEGROUPS/MYRESOURCEGROUP/PROVIDERS/MICROSOFT.NETWORK/NETWORKSECURITYGROUPS/MYNSG",
			"operationName": "NetworkSecurityGroupFlowEvents",
			"properties": {
				"Version": 1,
				"flows": [
					{
						"rule": "DefaultRule_AllowInternetOutBound",
						"flows": [
							{
								"mac": "000D3A18077E",
								"flowTuples": [
									"1497646722,10.0.0.4,168.62.32.14,44904,443,T,O,A",
									"1497646722,10.0.0.4,52.240.48.24,45218,443,T,O,A",
									"1497646725,10.0.0.4,168.62.32.14,44910,443,T,O,A",
									"1497646725,10.0.0.4,52.240.48.24,45224,443,T,O,A",
									"1497646728,10.0.0.4,168.62.32.14,44916,443,T,O,A",
									"1497646728,10.0.0.4,52.240.48.24,45230,443,T,O,A",
									"1497646732,10.0.0.4,168.62.32.14,44922,443,T,O,A",
									"1497646732,10.0.0.4,52.240.48.24,45236,443,T,O,A"
								]
							}
						]
					},
					{
						"rule": "DefaultRule_DenyAllInBound",
						"flows": []
					},
					{
						"rule": "UserRule_ssh-rule",
						"flows": []
					},
					{
						"rule": "UserRule_web-rule",
						"flows": [
							{
								"mac": "000D3A18077E",
								"flowTuples": [
									"1497646738,13.82.225.93,10.0.0.4,1180,80,T,I,A",
									"1497646750,13.82.225.93,10.0.0.4,1184,80,T,I,A",
									"1497646768,13.82.225.93,10.0.0.4,1181,80,T,I,A",
									"1497646780,13.82.225.93,10.0.0.4,1336,80,T,I,A"
								]
							}
						]
					}
				]
			}
		}
	]
}