Leggere i log dei flussi
Importante
Il 30 settembre 2027 i log dei flussi del gruppo di sicurezza di rete (NSG) verranno ritirati. Come parte di questo ritiro, non sarà più possibile creare nuovi log dei flussi del gruppo di sicurezza di rete a partire dal 30 giugno 2025. È consigliabile la migrazione ai log dei flussi della rete virtuale, che superano le limitazioni dei log dei flussi del gruppo di sicurezza di rete. Dopo la data di ritiro, l'analisi del traffico abilitata con i log dei flussi del gruppo di sicurezza di rete non sarà più supportata e le risorse dei log dei flussi del gruppo di sicurezza di rete esistenti nelle sottoscrizioni verranno eliminate. Tuttavia, i record dei log dei flussi del gruppo di sicurezza di rete non verranno eliminati e continueranno a seguire i rispettivi criteri di conservazione. Per altre informazioni, consultare l'annuncio ufficiale.
Questo articolo mostra come leggere in modo selettivo parti dei log dei flussi di Azure Network Watcher con 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. L’uso dello script fornito in questo articolo permette di leggere i dati più recenti dai log dei flussi senza dover scaricare l'intero log.
I concetti illustrati in questo articolo non si riferiscono solo a PowerShell ma si applicano a tutti i linguaggi supportati dalle API di Archiviazione di Azure.
Prerequisiti
Un account Azure con una sottoscrizione attiva. Creare un account gratuitamente.
PowerShell installato nel computer. Per altre informazioni, vedere Installare PowerShell in Windows, Linux e macOS. In questo articolo si presuppone che il modulo Azure PowerShell sia disponibile. Per altre informazioni, vedere Installare Azure PowerShell. Per trovare la versione installata, eseguire
Get-Module -ListAvailable Az
.Log dei flussi in una o più aree. Per altre informazioni, vedere Creare un log dei flussi per il gruppo di sicurezza di rete o Creare un log dei flussi per la rete virtuale.
Autorizzazioni di controllo degli accessi in base al ruolo necessarie per le sottoscrizioni dei log dei flussi e dell'account di archiviazione. Per altre informazioni, vedere Autorizzazioni di controllo degli accessi in base al ruolo di Network Watcher.
Recuperare l'elenco di elementi bloccati
Lo script PowerShell seguente imposta le variabili necessarie per eseguire una query sul BLOB del log del flussi del gruppo di sicurezza di rete ed elenca i blocchi all'interno del BLOB in blocchi CloudBlockBlob. Aggiornare lo script in modo che contenga valori validi per l’ambiente; in particolare "yourSubscriptionId", "FLOWLOGSVALIDATIONWESTCENTRALUS", "V2VALIDATIONVM-NSG", "yourStorageAccountName", "ml-rg", "000D3AF87856", "11/11/2018 03:00". Ad esempio, yourSubscriptionId deve essere sostituito con l'ID sottoscrizione.
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 contiene le parentesi 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 viene letta la variabile $blocklist
per recuperare i dati. Nell'esempio seguente viene eseguita l'iterazione dell'elenco di elementi bloccati per leggere i byte da ogni blocco e archiviarli in un array. 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
A questo punto l’array $valuearray
contiene 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é si tratta della parentesi di chiusura.
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/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/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"
]
}
]
}
]
}
}
]
}