Public/ConvertFrom-NSPNpsRadiusLog.ps1

function ConvertFrom-NSPNpsRadiusLog {
    <#
    .SYNOPSIS
        Reads NPS database-compatible CSV logs into named, decoded records.
    #>

    [CmdletBinding()]
    param([Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$Path)

    $fieldNames = @(
        'ComputerName', 'ServiceName', 'RecordDate', 'RecordTime', 'PacketType', 'UserName',
        'FullyQualifiedDistinguishedName', 'CalledStationID', 'CallingStationID', 'CallbackNumber',
        'FramedIPAddress', 'NASIdentifier', 'NASIPAddress', 'NASPort', 'ClientVendor', 'ClientIPAddress',
        'ClientFriendlyName', 'EventTimestamp', 'PortLimit', 'NASPortType', 'ConnectInfo', 'FramedProtocol',
        'ServiceType', 'AuthenticationType', 'PolicyName', 'ReasonCode', 'Class', 'SessionTimeout',
        'IdleTimeout', 'TerminationAction', 'EAPFriendlyName', 'AcctStatusType', 'AcctDelayTime',
        'AcctInputOctets', 'AcctOutputOctets', 'AcctSessionId', 'AcctAuthentic', 'AcctSessionTime',
        'AcctInputPackets', 'AcctOutputPackets', 'AcctTerminateCause', 'AcctMultiSsnID', 'AcctLinkCount',
        'AcctInterimInterval', 'TunnelType', 'TunnelMediumType', 'TunnelClientEndpt', 'TunnelServerEndpt',
        'AcctTunnelConn', 'TunnelPvtGroupID', 'TunnelAssignmentID', 'TunnelPreference', 'MSAcctAuthType',
        'MSAcctEAPType', 'MSRASVersion', 'MSRASVendor', 'MSCHAPError', 'MSCHAPDomain',
        'MSMPPEEncryptionTypes', 'MSMPPEEncryptionPolicy', 'ProxyPolicyName', 'ProviderType',
        'ProviderName', 'RemoteServerAddress', 'MSRASClientName', 'MSRASClientVersion'
    )
    $packetTypes = @{ '1'='Access-Request'; '2'='Access-Accept'; '3'='Access-Reject'; '4'='Accounting-Request'; '5'='Accounting-Response'; '11'='Access-Challenge' }
    $authTypes = @{ '1'='PAP'; '2'='CHAP'; '3'='MS-CHAP'; '4'='MS-CHAP v2'; '5'='EAP'; '7'='None'; '8'='Custom' }
    $reasonCodes = @{
        '0'='Success'; '1'='Internal error'; '2'='Access denied'; '3'='Malformed request'; '4'='Global catalog unavailable'
        '5'='Domain unavailable'; '6'='Server unavailable'; '7'='No such domain'; '8'='No such user'
        '16'='Authentication failure'; '17'='Password change failure'; '18'='Unsupported authentication type'
        '32'='Local users only'; '33'='Password must change'; '34'='Account disabled'; '35'='Account expired'
        '36'='Account locked out'; '37'='Invalid logon hours'; '38'='Account restriction'
        '48'='Did not match network policy'; '49'='Did not match connection request policy'
        '64'='Dial-in locked out'; '65'='Dial-in disabled'; '66'='Invalid authentication type'
        '67'='Invalid calling station'; '68'='Invalid dial-in hours'; '69'='Invalid called station'
        '70'='Invalid port type'; '71'='Invalid restriction'; '80'='No record'; '96'='Session timed out'
        '97'='Unexpected request'
    }
    $providerTypes = @{ '0'='None'; '1'='Windows (local)'; '2'='RADIUS Proxy' }

    $resolved = (Resolve-Path -LiteralPath $Path -ErrorAction Stop).ProviderPath
    foreach ($row in (Import-Csv -LiteralPath $resolved -Header $fieldNames -ErrorAction Stop)) {
        $packet = if ($packetTypes.ContainsKey($row.PacketType)) { $packetTypes[$row.PacketType] } else { "Unknown ($($row.PacketType))" }
        $auth = if ($authTypes.ContainsKey($row.AuthenticationType)) { $authTypes[$row.AuthenticationType] } else { $row.AuthenticationType }
        $reason = if ($reasonCodes.ContainsKey($row.ReasonCode)) { $reasonCodes[$row.ReasonCode] } else { $row.ReasonCode }
        $provider = if ($providerTypes.ContainsKey($row.ProviderType)) { $providerTypes[$row.ProviderType] } else { $row.ProviderType }
        [pscustomobject]@{
            RadiusServer = $row.ComputerName
            ServiceName = $row.ServiceName
            RecordDate = $row.RecordDate
            RecordTime = $row.RecordTime
            PacketTypeRaw = $row.PacketType
            PacketType = $packet
            UserName = $row.UserName
            UserFQDN = $row.FullyQualifiedDistinguishedName
            CalledStationID = $row.CalledStationID
            CallingStationID = $row.CallingStationID
            NASIdentifier = $row.NASIdentifier
            NASIPAddress = $row.NASIPAddress
            ClientVendor = $row.ClientVendor
            ClientIPAddress = $row.ClientIPAddress
            ClientFriendlyName = $row.ClientFriendlyName
            NASPortType = $row.NASPortType
            ConnectInfo = $row.ConnectInfo
            FramedIPAddress = $row.FramedIPAddress
            AuthenticationTypeRaw = $row.AuthenticationType
            AuthenticationType = $auth
            EAPFriendlyName = $row.EAPFriendlyName
            MSRASClientName = $row.MSRASClientName
            MSRASClientVersion = $row.MSRASClientVersion
            PolicyName = $row.PolicyName
            ReasonCodeRaw = $row.ReasonCode
            ReasonCode = $reason
            Class = $row.Class
            ProxyPolicyName = $row.ProxyPolicyName
            ProviderTypeRaw = $row.ProviderType
            ProviderType = $provider
            _Raw = $row
        }
    }
}