User Tools

Site Tools


powershell:nps:radiuscopy

PS script to Copy Radius clients

This script can be (modifed) and used to sync all radius clients over multiple NPS servers (the server running the script is master). In addition it will create Custom Event views, for each Radius client, making it so much easier to use the logs.

#Add list of NPS Servers here
$NPSServers = @("Server1","Server2","Server3")
 
 
[string]$EventViewPath = "C:\ProgramData\Microsoft\Event Viewer\Views\NPS"
[string]$EventViewPath_REMOTE = "c$\ProgramData\Microsoft\Event Viewer\Views\NPS"
 
 
function VerifyAdmin
{
    $Elevated = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent() )
    & {
        if ($Elevated.IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator ))
        {
 
            write-host "PowerShell is running as an administrator." -ForegroundColor Green 
        } Else {
		    throw "Powershell must be run as an adminstrator."
	    }
 
        if( [IntPtr]::size * 8 -eq 64 )
        {
		    Write-Host "You are running 64-bit PowerShell" -ForegroundColor Green 
 
        }
        else
        {
		    Write-Host "You are running 32-bit PowerShell" -ForegroundColor Red 
		    Throw "Please run using 64-bit PowerShell as administrator" 
        }
    }
}
# ----------------------------------------
# 		END OF POWERSHELL CHECK
# ----------------------------------------
 
 
 
function EmptyViews-Local()
{
    if ((Test-Path -Path $EventViewPath) -eq $false)
    {
        New-Item -Path $EventViewPath -type directory
    }
    Remove-Item -Path "$EventViewPath\*" -Recurse
}
 
function EmptyViews([string]$Server)
{
    [string] $Path = "\\$Server\$EventViewPath_REMOTE"
    if ((Test-Path -Path $Path) -eq $false)
    {
        New-Item -Path $Path -type directory
    }
    Remove-Item -Path "$Path\*"  -Recurse
}
 
 
# Get the Location from the Name of the Switch
 
function GetRadiusClientEnvironment([string]$Name)
{
    $NameArray = $Name.Split("-")
    if ($NameArray.Count -le 2)
    {
        return $Null  #Not a standard name
    }
    return $NameArray[1]
}
 
function CreateCustomView-Local([string]$IP,[string]$Name,[int]$ID)
{
 
    [string]$XmlData="<ViewerConfig><QueryConfig><QueryParams><UserQuery /></QueryParams><QueryNode><Name LanguageNeutralValue=`"$Name`">$Name</Name><QueryList><Query Id=`"0`" Path=`"Security`"><Select Path=`"Security`">*[EventData[Data[@Name='ClientName']='$NAME']]</Select></Query></QueryList></QueryNode></QueryConfig></ViewerConfig>"
 
    [string]$Location = GetRadiusClientEnvironment $Name
 
    if ($Location -ne "") # Powershell does not really handle $Null correct, check for empty string instead
    {
 
        if ((Test-Path -Path "$EventViewPath\$Location" -PathType Container) -eq $false)
        {
            $D = New-Item -Path "$EventViewPath\$Location" -type directory 
        }
        Add-Content -Path "$EventViewPath\$Location\View_$ID.xml" -Value $XmlData
    }
    else
    {
        Add-Content -Path "$EventViewPath\View_$ID.xml" -Value $XmlData
    }
}
 
function CreateCustomView([string]$IP,[string]$Name,[int]$ID,[string]$Server)
{
    [string]$XmlData="<ViewerConfig><QueryConfig><QueryParams><UserQuery /></QueryParams><QueryNode><Name LanguageNeutralValue=`"$Name`">$Name</Name><QueryList><Query Id=`"0`" Path=`"Security`"><Select Path=`"Security`">*[EventData[Data[@Name='ClientName']='$NAME']]</Select></Query></QueryList></QueryNode></QueryConfig></ViewerConfig>"
 
    [string]$Location = GetRadiusClientEnvironment $Name
 
    if ($Location -ne "") # Powershell does not really handle $Null correct, check for empty string instead
    {
        if ((Test-Path -Path "\\$Server\$EventViewPath_REMOTE\$Location" -PathType Container) -eq $false)
        {
            $D = New-Item -Path "\\$Server\$EventViewPath_REMOTE\$Location" -type directory 
        }
        Add-Content -Path "\\$Server\$EventViewPath_REMOTE\$Location\View_$ID.xml" -Value $XmlData
    }
    else
    {
 
        Add-Content -Path "\\$Server\$EventViewPath_REMOTE\View_$ID.xml" -Value $XmlData
    }
 
}
 
 
 
# This function will create the quick access search list
function CreateCustomHelperViews([string]$Server)
{
 
    if ((Test-Path -Path "\\$Server\$EventViewPath_REMOTE\_QuickSearches" -PathType Container) -eq $false)
    {
        $D = New-Item -Path "\\$Server\$EventViewPath_REMOTE\_QuickSearches" -type directory 
    }
    [string]$FindByHostName="<ViewerConfig><QueryConfig><QueryParams><UserQuery /></QueryParams><QueryNode><Name LanguageNeutralValue=`"Find by HostName`">Find by HostName</Name><QueryList><Query Id=`"0`" Path=`"Security`"><Select Path=`"Security`">*[EventData[Data[@Name='FullyQualifiedSubjectUserName']='PERTRA\DNDZ27370$']]</Select></Query></QueryList></QueryNode></QueryConfig></ViewerConfig>"
    Add-Content -Path "\\$Server\$EventViewPath_REMOTE\_QuickSearches\View_ByHostName.xml" -Value $FindByHostName
 
    [string]$FindByMac="<ViewerConfig><QueryConfig><QueryParams><UserQuery /></QueryParams><QueryNode><Name LanguageNeutralValue=`"Find by MAC`">Find by MAC</Name><QueryList><Query Id=`"0`" Path=`"Security`"><Select Path=`"Security`">*[EventData[Data[@Name='CallingStationID']='6c-c2-17-7f-25-64']]</Select></Query></QueryList></QueryNode></QueryConfig></ViewerConfig>"
    Add-Content -Path "\\$Server\$EventViewPath_REMOTE\_QuickSearches\View_ByMac.xml" -Value $FindByMac
 
    [string]$FindByUserName="<ViewerConfig><QueryConfig><QueryParams><UserQuery /></QueryParams><QueryNode><Name LanguageNeutralValue=`"Find by UserName`">Find by UserName</Name><QueryList><Query Id=`"0`" Path=`"Security`"><Select Path=`"Security`">*[EventData[Data[@Name='SubjectUserName']='terped']]</Select></Query></QueryList></QueryNode></QueryConfig></ViewerConfig>"
    Add-Content -Path "\\$Server\$EventViewPath_REMOTE\_QuickSearches\View_ByUserName.xml" -Value $FindByUserName
 
 
    [string]$AllWarnings="<ViewerConfig><QueryConfig><QueryParams><UserQuery /></QueryParams><QueryNode><Name LanguageNeutralValue=`"All Denied`">All Denied</Name><QueryList><Query Id=`"0`" Path=`"System`"><Select Path=`"System`">*[System[Provider[@Name='NPS']]]</Select><Select Path=`"System`">*[System[Provider[@Name='HRA']]]</Select><Select Path=`"System`">*[System[Provider[@Name='Microsoft-Windows-HCAP']]]</Select><Select Path=`"Security`">*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID = 6273]]</Select></Query></QueryList></QueryNode></QueryConfig></ViewerConfig>"
    Add-Content -Path "\\$Server\$EventViewPath_REMOTE\_QuickSearches\View_Warings.xml" -Value $AllWarnings
 
 
}
# This function will create the quick access search list
function CreateCustomHelperViews-local()
{
 
    if ((Test-Path -Path "$EventViewPath\_QuickSearches" -PathType Container) -eq $false)
    {
        $D = New-Item -Path "$EventViewPath\_QuickSearches" -type directory 
    }
    [string]$FindByHostName="<ViewerConfig><QueryConfig><QueryParams><UserQuery /></QueryParams><QueryNode><Name LanguageNeutralValue=`"Find by HostName`">Find by HostName</Name><QueryList><Query Id=`"0`" Path=`"Security`"><Select Path=`"Security`">*[EventData[Data[@Name='FullyQualifiedSubjectUserName']='PERTRA\DNDZ27370$']]</Select></Query></QueryList></QueryNode></QueryConfig></ViewerConfig>"
    Add-Content -Path "$EventViewPath\_QuickSearches\View_ByHostName.xml" -Value $FindByHostName
 
    [string]$FindByMac="<ViewerConfig><QueryConfig><QueryParams><UserQuery /></QueryParams><QueryNode><Name LanguageNeutralValue=`"Find by MAC`">Find by MAC</Name><QueryList><Query Id=`"0`" Path=`"Security`"><Select Path=`"Security`">*[EventData[Data[@Name='CallingStationID']='6c-c2-17-7f-25-64']]</Select></Query></QueryList></QueryNode></QueryConfig></ViewerConfig>"
    Add-Content -Path "$EventViewPath\_QuickSearches\View_ByMac.xml" -Value $FindByMac
 
    [string]$FindByUserName="<ViewerConfig><QueryConfig><QueryParams><UserQuery /></QueryParams><QueryNode><Name LanguageNeutralValue=`"Find by UserName`">Find by UserName</Name><QueryList><Query Id=`"0`" Path=`"Security`"><Select Path=`"Security`">*[EventData[Data[@Name='SubjectUserName']='terped']]</Select></Query></QueryList></QueryNode></QueryConfig></ViewerConfig>"
    Add-Content -Path "$EventViewPath\_QuickSearches\View_ByUserName.xml" -Value $FindByUserName
 
 
    [string]$AllWarnings="<ViewerConfig><QueryConfig><QueryParams><UserQuery /></QueryParams><QueryNode><Name LanguageNeutralValue=`"All Denied`">All Denied</Name><QueryList><Query Id=`"0`" Path=`"System`"><Select Path=`"System`">*[System[Provider[@Name='NPS']]]</Select><Select Path=`"System`">*[System[Provider[@Name='HRA']]]</Select><Select Path=`"System`">*[System[Provider[@Name='Microsoft-Windows-HCAP']]]</Select><Select Path=`"Security`">*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID = 6273]]</Select></Query></QueryList></QueryNode></QueryConfig></ViewerConfig>"
    Add-Content -Path "$EventViewPath\_QuickSearches\View_Warings.xml" -Value $AllWarnings
 
}
 
function RemoveRadiusClient([string]$Server,[string]$Name)
{
 
    $Error.Clear()
    $RemoteScript = "Remove-NpsRadiusClient -Name `"$Name`""
    $Result = Invoke-Command -ComputerName $Server -ScriptBlock { Invoke-Expression $args[0] } -ArgumentList $RemoteScript
 
   if ($Error.Count -ne 0)
   {
        Write-Host "Failed Delete RadiusClient $Name on Server $Server. Error: ($Error)"
        return $false
   }
   Write-Host "Deleted Radius Client($Name) on server: $Server"
   return $true
}
 
function CreateNewRadiusClient([string]$Server,[object]$MasterClient)
{
 
    $Error.Clear()
 
    if ($MasterClient.Enabled -eq $true)
    {
        $RemoteScript = "New-NpsRadiusClient -Name `"$($MasterClient.Name)`" -Address `"$($MasterClient.Address)`" -SharedSecret `"$($MasterClient.SharedSecret)`" -VendorName `"$($MasterClient.VendorName)`" -NapCompatible `$$($MasterClient.NapCompatible)"
    }
    else
    {
        $RemoteScript = "New-NpsRadiusClient -Name `"$($MasterClient.Name)`" -Address `"$($MasterClient.Address)`" -SharedSecret `"$($MasterClient.SharedSecret)`" -VendorName `"$($MasterClient.VendorName)`" -NapCompatible `$$($MasterClient.NapCompatible) -Disabled:`$true"
    }
   $Result = Invoke-Command -ComputerName $Server -ScriptBlock { Invoke-Expression $args[0] } -ArgumentList $RemoteScript
 
   if ($Error.Count -ne 0)
   {
        Write-Host "Failed Createe NewRadiusClient $($MasterClient.Name) on Server $Server. Error: ($Error)"
        return $false
   }
   Write-Host "Created new Radius Client($($MasterClient.Name)) on server: $Server"
 
   return $true
 
}
function UpdateRemoveRadiusClientByName([string]$Server,[string]$Name,[string]$UpdateString)
 
{
   $RemoteScript = "Set-NpsRadiusClient -Name $Name $UpdateString"
    $Error.Clear()
   $Result = Invoke-Command -ComputerName $Server -ScriptBlock { Invoke-Expression $args[0] } -ArgumentList $RemoteScript
 
   if ($Error.Count -ne 0)
   {
        WriteLogError "Failed to update RadiusClient $Name on Server $Server. Error: ($Error)"
        return $false
   }
 
    Write-Host "RadiusClient $Name on Server $Server. was updated."
    return $true
}
 
function CheckAndDeleteClients([object]$ValidClients,[object]$ClientToCheck,[string]$Server)
{
    [bool]$found = $false
    foreach ($CL in $ValidClients)
    {
        if ($CL.Name -eq $ClientToCheck.Name)
        {
            $found = $true
        }
    }
    if ($found -eq $false)
    {
        WriteLog "Deleted Radius Client on $Server, Not configured on Master. Name: $($ClientToCheck.Name) IP: $($ClientToCheck.Address) Secret: $($ClientToCheck.SharedSecret) Enabled: $($ClientToCheck.Enabled) NAP: $($ClientToCheck.NapCompatible) Vendor: $($ClientToCheck.VendorName)"
        $Result = RemoveRadiusClient $Server $ClientToCheck.Name
    }
}
 
 
# ListOfClient on the REMOTE Radius server
# RadiusClient is a single Rclient from the "Master" list
function CheckIfClientExists([object]$ListofClients,[object]$RadiusClient,[string]$Server)
{
    foreach ($C in $ListofClients)
    {
        [int]$NeedUpdate = 0
        [string]$UpdateString =""
 
        if ($C.Address -eq $RadiusClient.Address)
        {
            # Client Exists, Check if data is the same
            if ($C.Name -ne $RadiusClient.Name)
            {
                Write-Host "RadiusClient with IP: $($RadiusClient.Address) has changed name. Needs to be deleted and recreated"
                $Res = RemoveRadiusClient $Server $C.Name
                if ($Res -eq $true)
                {
                     $Res = CreateNewRadiusClient $Server $RadiusClient
 
                }
            }
            else
            {
                if ($C.Enabled -ne $RadiusClient.Enabled)
                {
                    $NeedUpdate++
                    $UpdateString += "-Enabled `$$($RadiusClient.Enabled) "
                }
                if ($C.SharedSecret -ne $RadiusClient.SharedSecret)
                {
                    $NeedUpdate++
                    $UpdateString += "-SharedSecret `"$($RadiusClient.SharedSecret)`" "
                }
                if ($C.VendorName -ne $RadiusClient.VendorName)
                {
                    $NeedUpdate++
                    $UpdateString += "-VendorName `"$($RadiusClient.VendorName)`" "
                }
                if ($C.NapCompatible -ne $RadiusClient.NapCompatible)
                {
                    $NeedUpdate++
                    $UpdateString += "-NapCompatible `$$($RadiusClient.NapCompatible) "
                }
 
                if ($NeedUpdate -ne 0)
                {
                    $Res = UpdateRemoveRadiusClientByName $Server $C.Name $UpdateString
 
                }
            }
 
 
 
 
            return $true
        }
    }
# Check for any client that has been changed IP address
    foreach ($C in $ListofClients)
    {
        if ($C.Name -eq $RadiusClient.Name)
        {
            if ($C.Address -ne $RadiusClient.Address)
            {
                [string]$UpdateString =""
                #Radius Client has new IP address, but same name
                $UpdateString += "-Address `"$($RadiusClient.Address)`" "
                if ($C.Enabled -ne $RadiusClient.Enabled)
                {
                    $UpdateString += "-Enabled `$$($RadiusClient.Enabled) "
                }
                if ($C.SharedSecret -ne $RadiusClient.SharedSecret)
                {
                    $UpdateString += "-SharedSecret `"$($RadiusClient.SharedSecret)`" "
                }
                if ($C.VendorName -ne $RadiusClient.VendorName)
                {
                    $UpdateString += "-VendorName `"$($RadiusClient.VendorName)`" "
                }
                if ($C.NapCompatible -ne $RadiusClient.NapCompatible)
                {
                    $UpdateString += "-NapCompatible `$$($RadiusClient.NapCompatible) "
                }
                #Write-Host $UpdateString
                $Res = UpdateRemoveRadiusClientByName $Server $C.Name $UpdateString
                return $true
            }
        }
    }
 
 
    return $false
}
 
 
 
# Get a list of Local Radius Clients
VerifyAdmin
 
$CU = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
Write-Host "---Run RadiusClientsSync on $([DateTime]::Now) by $CU."
 
 
$Clients = Get-NpsRadiusClient
 
# Validate All Local Clients
[bool]$Validated = $true
foreach ($C in $Clients)
{
    if (($C.SharedSecret -eq "") -or ($C.SharedSecret -eq $null))
    {
        Write-Host "Master has an invalid Radius Client: $($C.Name) this must be removed before sync is preformed!"
        $Validated = $false
    }
}
if ($Validated -eq $false)
{
    return  # Break out of script.. There is some errors...
}
 
 
# Update Local Custom Views
EmptyViews-Local
[int]$IDCounter = 1
foreach ($C in $Clients)
{
    CreateCustomView-Local $C.Address $C.Name $IDCounter
    $IDCounter++
}
 
CreateCustomHelperViews-local
 
foreach ($Server in $NPSServers)
{
    WriteLog "Updating Radius Clients"
 
    $RemoteClients = Invoke-Command -ComputerName $Server -ScriptBlock { Get-NpsRadiusClient}
 
    #Check what's missing
    foreach ($C in $Clients)
    {
        $Res =  CheckIfClientExists $RemoteClients $C $Server
        if ($Res -eq $false)
        {
            # Create NEW
            CreateNewRadiusClient $Server $C
        }
    }
    # Check if Remote Server has Clients we are not aware off
 
    # Re-Read clients, incase we have deleted/created any new clients
    $RemoteClients = Invoke-Command -ComputerName $Server -ScriptBlock { Get-NpsRadiusClient}
 
    foreach ($RC in $RemoteClients)
    {
        CheckAndDeleteClients $Clients $RC $Server
    }
    Write-Host "Creating Custom Event Views"
 
    EmptyViews $Server
    # RE-Read Again to run CustomViews
    $RemoteClients = Invoke-Command -ComputerName $Server -ScriptBlock { Get-NpsRadiusClient}
    [int]$ID = 0
    foreach ($RC in $RemoteClients)
    {
        CreateCustomView $RC.Address $RC.Name $ID $Server
        $ID++;
    }
    CreateCustomHelperViews $Server
 
}
powershell/nps/radiuscopy.txt ยท Last modified: 2018/11/30 00:56 by admin