フロー ログの読み取り

この記事では、ログ全体を解析することなく、PowerShell を使用して Azure Network Watcher フロー ログの一部を選択的に読み取る方法について説明します。 フロー ログは、ブロック BLOB のストレージ アカウントに保存されます。 各ログは、1 時間ごとに生成され、数分ごとに最新のデータで更新される個別のブロック BLOB です。 この記事で提供されているスクリプトを使用すると、ログ全体をダウンロードしなくても、フロー ログから最新のデータを読み取ることができます。

この記事で説明する概念は PowerShell に制限されず、Azure Storage API でサポートされるすべての言語に適用できます。

前提条件

ブロックリストを取得する

次の PowerShell スクリプトは、NSG フロー ログの BLOB にクエリを実行し、CloudBlockBlob ブロック BLOB 内のブロックを一覧表示するために必要な変数を設定します。 スクリプトを更新して、使用している環境で有効な値を格納するようにします。

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 NSG 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 NSG flow logs
        $ContainerName = "insights-logs-networksecuritygroupflowevent"

        # Name of the blob that contains the NSG 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

$blockList 変数は BLOB 内のブロックの一覧を返します。 各ブロック BLOB には、少なくとも 2 つのブロックが含まれています。 最初のブロックの長さは 12 バイトで、JSON 形式のログの左角かっこが格納されます。 他のブロックは右角かっこで、長さは 2 バイトです。 次の例のログには、7 つの個別のエントリがあります。 ログの新規エントリはすべて末尾の、最後のブロックの直前に追加されます。

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

ブロック BLOB を読み取る

このセクションでは、$blocklist 変数を読み取って、データを取得します。 次の例では、ブロック リストを反復処理して各ブロックからバイトを読み取り、配列に格納します。 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

$valuearray 配列には各ブロックの文字列値が格納されています。 エントリの内容を確認するため、$valuearray[$valuearray.Length-2] を実行して配列の 2 番めから最後の値を取得します。 最後の値は右角かっこであるため、必要ありません。

この値の結果を次の例に示します。

{
	"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"
								]
							}
						]
					}
				]
			}
		}
	]
}