Ler os logs de fluxo

Importante

Os logs de fluxo do NSG (grupo de segurança de rede) serão desativados em 30 de setembro de 2027. Como o recurso está sendo descontinuado, ele não dá mais suporte à criação de novos logs de fluxo de NSG. Migre para logs de fluxo da rede virtual, que resolvem as limitações dos logs de fluxo do NSG. Após a data de desativação, o Azure não dará mais suporte à análise de tráfego habilitada para os logs de fluxo do NSG e excluirá os recursos existentes de logs de fluxo do NSG em suas assinaturas. No entanto, o Azure não exclui registros existentes de log de fluxo NSG do Armazenamento do Azure e continua seguindo suas políticas de retenção configuradas. Para saber mais, confira o anúncio oficial.

Neste artigo, você vai aprender a ler seletivamente partes dos logs de fluxo do Observador de Rede do Azure usando o PowerShell sem precisar analisar o log inteiro. Os logs de fluxo são armazenados em uma conta de armazenamento em blobs de bloco. Cada log é um blob de blocos separado que é gerado a cada hora e atualizado com os dados mais recentes a cada poucos minutos. Usando o script fornecido neste artigo, você poderá ler os dados mais recentes dos logs de fluxo sem precisar baixar o log inteiro.

Os conceitos discutidos neste artigo não se limitam ao PowerShell e são aplicáveis a todas as linguagens compatíveis com as APIs de Armazenamento do Azure.

Pré-requisitos

Recuperar a lista de bloqueios

Nesta seção, você configurará as variáveis necessárias para consultar o blob de log de fluxo e listar os blocos dentro do blob de blocos CloudBlockBlob.

Atualize o script do PowerShell com valores válidos para seu ambiente.

function Get-VNetFlowLogCloudBlockBlob {
    [CmdletBinding()]
    param (
        [string] [Parameter(Mandatory=$true)] $subscriptionId,
        [string] [Parameter(Mandatory=$true)] $region,
        [string] [Parameter(Mandatory=$true)] $VNetFlowLogName,
        [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 virtual network flow 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 virtual network flow logs
        $ContainerName = "insights-logs-flowlogflowevent"

        # Name of the blob that contains the virtual network flow log
        $BlobName = "flowLogResourceID=/$($subscriptionId.ToUpper())_NETWORKWATCHERRG/NETWORKWATCHER_$($region.ToUpper())_$($VNetFlowLogName.ToUpper())/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-VNetFlowLogBlockList  {
    [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-VNetFlowLogCloudBlockBlob -subscriptionId "yourSubscriptionId" -region "yourVNetFlowLogRegion" -VNetFlowLogName "yourVNetFlowLogName" -storageAccountName "yourStorageAccountName" -storageAccountResourceGroup "yourStorageAccountRG" -macAddress "0022485D8CF8" -logTime "07/09/2023 03:00" 

$blockList = Get-VNetFlowLogBlockList -CloudBlockBlob $CloudBlockBlob

A variável $blockList retorna uma lista dos blocos no blob. Cada blob de blocos contém pelo menos dois blocos. O primeiro bloco tem um comprimento de 12 bytes e contém os colchetes de abertura do log JSON. O outro bloco consiste nos colchetes de fechamento e tem um comprimento de 2 bytes. O exemplo de log a seguir contém sete entradas individuais. Todas as novas entradas no log são adicionadas ao final logo antes do bloco final.

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

Ler o blob de blocos

Nessa seção, você vai ler a variável $blocklist para recuperar os dados. No exemplo a seguir, iteramos pela lista de blocos para ler os bytes de cada bloco e armazená-los em um array. Use o método DownloadRangeToByteArray para recuperar os dados.

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

    )
    $blocklistResult = $blockList.Result
    
    # Set the size of the byte array to the largest block
    $maxvalue = ($blocklistResult | Measure-Object Length -Maximum).Maximum
    Write-Host "Max value is ${maxvalue}"

    # 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 $blocklistResult.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, $($blockListResult[$i].Length)) | Out-Null

        # Increment the index by adding the current block length to the previous index
        $index = $index + $blockListResult[$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-VNetFlowLogReadBlock -blockList $blockList -CloudBlockBlob $CloudBlockBlob

A matriz $valuearray agora contém o valor de cadeia de caracteres de cada bloco. Para verificar a entrada, obtenha do segundo ao último valor da matriz executando $valuearray[$valuearray.Length-2]. Você não precisa do último valor porque é o colchete de fechamento.

Os resultados desse valor são mostrados no exemplo a seguir:

{
    "time": "2023-07-09T03:59:30.2837112Z",
    "flowLogVersion": 4,
    "flowLogGUID": "abcdef01-2345-6789-0abc-def012345678",
    "macAddress": "0022485D8CF8",
    "category": "FlowLogFlowEvent",
    "flowLogResourceID": "/SUBSCRIPTIONS/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/RESOURCEGROUPS/NETWORKWATCHERRG/PROVIDERS/MICROSOFT.NETWORK/NETWORKWATCHERS/NETWORKWATCHER_EASTUS/FLOWLOGS/MYVNET-MYRESOURCEGROUP-FLOWLOG",
    "targetResourceID": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVNet",
    "operationName": "FlowLogFlowEvent",
    "flowRecords": {
        "flows": [
            {
                "aclID": "00000000-1234-abcd-ef00-c1c2c3c4c5c6",
                "flowGroups": [
                    {
                        "rule": "BlockHighRiskTCPPortsFromInternet",
                        "flowTuples": [
                            "1688875131557,45.119.212.87,192.168.0.4,53018,3389,6,I,D,NX,0,0,0,0"
                        ]
                    },
                    {
                        "rule": "Internet",
                        "flowTuples": [
                            "1688875103311,35.203.210.145,192.168.0.4,56688,52113,6,I,D,NX,0,0,0,0",
                            "1688875119073,162.216.150.87,192.168.0.4,50111,9920,6,I,D,NX,0,0,0,0",
                            "1688875119910,205.210.31.253,192.168.0.4,54699,1801,6,I,D,NX,0,0,0,0",
                            "1688875121510,35.203.210.49,192.168.0.4,49250,33013,6,I,D,NX,0,0,0,0",
                            "1688875121684,162.216.149.206,192.168.0.4,49776,1290,6,I,D,NX,0,0,0,0",
                            "1688875124012,91.148.190.134,192.168.0.4,57963,40544,6,I,D,NX,0,0,0,0",
                            "1688875138568,35.203.211.204,192.168.0.4,51309,46956,6,I,D,NX,0,0,0,0",
                            "1688875142490,205.210.31.18,192.168.0.4,54140,30303,6,I,D,NX,0,0,0,0",
                            "1688875147864,194.26.135.247,192.168.0.4,53583,20232,6,I,D,NX,0,0,0,0"
                        ]
                    }
                ]
            }
        ]
    }
}